* @author Aurelien Bompard */ // must be run within Dokuwiki if(!defined('DOKU_INC')) die(); require_once DOKU_PLUGIN . 'odt/helper/cssimport.php'; require_once DOKU_PLUGIN . 'odt/ODT/ODTDefaultStyles.php'; // Central class for ODT export require_once DOKU_PLUGIN . 'odt/ODT/ODTDocument.php'; /** * The Page Renderer * * @package DokuWiki\Renderer\Page */ class renderer_plugin_odt_page extends Doku_Renderer { /** @var helper_plugin_odt_cssimport */ protected $import = null; /** @var helper_plugin_odt_config */ protected $config = null; protected $document = null; /** @var string */ protected $css; /** @var bool */ protected $init_ok; /** * Constructor. Loads helper plugins. */ public function __construct() { // Set up empty array with known config parameters $this->config = plugin_load('helper', 'odt_config'); // Create and initialize document $this->document = new ODTDocument(); $this->init_ok = $this->document->initialize (); } /** * Set a config parameter from extern. */ public function setConfigParam($name, $value) { $this->config->setParam($name, $value); } /** * Is the $string specified the name of a ODT plugin config parameter? * * @return bool Is it a config parameter? */ public function isConfigParam($string) { return $this->config->isParam($string); } /** * Returns the format produced by this renderer. */ function getFormat(){ return "odt"; } /** * Do not make multiple instances of this class */ function isSingleton(){ return true; } public function replaceURLPrefixesCallback ($property, $value, $url) { if (strncmp($url, '/lib/plugins', strlen('/lib/plugins')) == 0) { return DOKU_INC.substr($url,1); } return $url; } /** * Load and imports CSS. */ protected function load_css() { global $conf, $lang; /** @var helper_plugin_odt_dwcssloader $loader */ $loader = plugin_load('helper', 'odt_dwcssloader'); if ( isset($loader) ) { $this->css = $loader->load ('odt', 'odt', $this->config->getParam('css_template')); } // Import CSS (old API, deprecated) $this->import = plugin_load('helper', 'odt_cssimport'); if ( isset($this->import) ) { $this->import->importFromString ($this->css); // Call adjustLengthValues to make our callback function being called for every // length value imported. This gives us the chance to convert it once from // pixel to points. $this->import->adjustLengthValues (array($this, 'adjustLengthCallback')); } // Set CSS usage according to configuration switch ($this->config->getParam('css_usage')) { case 'basic style import': $this->document->setCSSUsage('basic'); break; case 'full': $this->document->setCSSUsage('full'); break; default: $this->document->setCSSUsage('off'); break; } $this->document->setMediaSelector($this->config->getParam('media_sel')); // Put some root element on the HTML stack which should always // be present for our CSS matching $this->document->addHTMLElement ('html', 'lang="'.$conf['lang'].'" dir="'.$lang['direction'].'"'); $this->document->addHTMLElement ('body'); $this->document->addHTMLElement ('div', 'id="dokuwiki__site"'); $this->document->addHTMLElement ('div', 'id="dokuwiki__top" class="site dokuwiki mode_show tpl_adoradark loggedIn"'); $this->document->addHTMLElement ('div', 'id="dokuwiki__content"'); $this->document->addHTMLElement ('div', 'class="page group"'); // Import CSS (new API) $this->document->importCSSFromString ($this->css, $this->config->getParam('media_sel'), array($this, 'replaceURLPrefixesCallback'), false, $this->config->getParam('olist_label_align')); } /** * Configure units to our configuration values. */ protected function setupUnits() { $this->document->setPixelPerEm($this->config->getParam ('css_font_size')); $this->document->setTwipsPerPixelX($this->config->getParam ('twips_per_pixel_x')); $this->document->setTwipsPerPixelY($this->config->getParam ('twips_per_pixel_y')); } /** * Initialize the document, * Do the things that are common to all documents regardless of the * output format (ODT or PDF). */ function document_setup() { global $ID; // First, get export mode. $warning = ''; $mode = $this->config->load($warning); // Setup Units before CSS import! $this->setupUnits(); switch($mode) { case 'ODT template': case 'CSS template': break; default: // Set ordered list alignment before calling load_css(). // load_css() will eventually overwrite the list settings! $this->document->setOrderedListParams(NULL, $this->config->getParam('olist_label_align')); $this->document->setUnorderedListParams(NULL, $this->config->getParam('olist_label_align')); break; } // Import CSS files $this->load_css(); switch($mode) { case 'ODT template': // Document based on ODT template. $this->buildODTPathes ($ODTtemplate, $temp_dir); $this->document->importODTStyles($ODTtemplate, $temp_dir); if ($this->config->getParam ('apply_fs_to_non_css')) { $this->document->adjustFontSizes($this->config->getParam('css_font_size').'pt'); } break; case 'CSS template': // Document based on DokuWiki CSS template. $media_sel = $this->config->getParam ('media_sel'); $template = $this->config->getParam ('odt_template'); $directory = $this->config->getParam ('tpl_dir'); $template_path = $this->config->getParam('mediadir').'/'.$directory."/".$template; $this->document->importCSSFromFile ($template_path, $media_sel, array($this, 'replaceURLPrefixesCallback'), $this->config->getParam('olist_label_align')); // Set outline style. $this->document->setOutlineStyle($this->config->getParam('outline_list_style')); break; default: // Document from scratch. // Set outline style. $this->document->setOutlineStyle($this->config->getParam('outline_list_style')); if ($this->config->getParam ('apply_fs_to_non_css')) { $this->document->adjustFontSizes($this->config->getParam('css_font_size').'pt'); } break; } // If we are using ODT for style import (a template or the default 'styles.xml') // then adjust the pixel per em value to the font-size of the default paragraph style // otherwise plugins might inherit a wrong font-size on CSS import! if ($mode != 'CSS template') { $default = $this->document->getDefaultStyle ('paragraph'); if (isset($default)) { $fontFize = $default->getProperty('font-size'); if (!empty($fontFize)) { $fontFizeInPx = $this->document->toPixel($fontFize); if (!empty($fontFizeInPx)) { $this->document->setPixelPerEm($fontFizeInPx); } } } } // Setup page format. $this->document->setStartPageFormat ($this->config->getParam ('format'), $this->config->getParam ('orientation'), $this->config->getParam ('margin_top'), $this->config->getParam ('margin_right'), $this->config->getParam ('margin_bottom'), $this->config->getParam ('margin_left')); // Set title in meta info. // FIXME article title != book title SOLUTION: overwrite at the end for book $this->document->setTitle($ID); // Enable/disable links according to configuration $disabled = $this->config->getParam ('disable_links'); if ($disabled) { $this->document->disableLinks(); } else { $this->document->enableLinks(); } $this->set_page_bookmark($ID); } /** * Initialize the rendering */ function document_start() { global $ID; if (!$this->init_ok) { // Initialization of the ODT document failed! // Send "Internal Server Error" http_status(500); $message = $this->getLang('init_failed_msg'); $message = str_replace('%DWVERSION%', getVersion(), $message); $instructions = p_get_instructions($message); print p_render('xhtml', $instructions, $info); exit; } // Initialize the document $this->document_setup(); // Create HTTP headers $output_filename = str_replace(':','-',$ID).'.odt'; $headers = array( 'Content-Type' => 'application/vnd.oasis.opendocument.text', 'Content-Disposition' => 'attachment; filename="'.$output_filename.'";', ); // store the content type headers in metadata p_set_metadata($ID,array('format' => array('odt_page' => $headers) )); } /** * Closes the document */ function document_end(){ // Build the document $this->finalize_ODTfile(); // Refresh certain config parameters e.g. 'disable_links' $this->config->refresh(); // Reset state. $this->document->state->reset(); } /** * This function sets the page format. * The format, orientation and page margins can be changed. * See function queryFormat() in ODT/page.php for supported formats. * * @param string $format e.g. 'A4', 'A3' * @param string $orientation e.g. 'portrait' or 'landscape' * @param numeric $margin_top Top-Margin in cm, default 2 * @param numeric $margin_right Right-Margin in cm, default 2 * @param numeric $margin_bottom Bottom-Margin in cm, default 2 * @param numeric $margin_left Left-Margin in cm, default 2 * @see ODTDocument::setPageFormat */ public function setPageFormat ($format=NULL, $orientation=NULL, $margin_top=NULL, $margin_right=NULL, $margin_bottom=NULL, $margin_left=NULL) { $this->document->setPageFormat ($format, $orientation, $margin_top, $margin_right, $margin_bottom, $margin_left); } /** * Completes the ODT file. */ public function finalize_ODTfile() { global $ID; $this->buildODTPathes ($ODTtemplate, $temp_dir); // Build/assign the document $this->doc = $this->document->getODTFileAsString ($ODTtemplate, $temp_dir); } /** * Simple setter to enable creating links. */ function enable_links() { $this->config->setParam ('disable_links', false); $this->document->enableLinks(); } /** * Simple setter to disable creating links. */ function disable_links() { $this->config->setParam ('disable_links', true); $this->document->disableLinks(); } /** * Dummy function. * * @return string */ function render_TOC() { return ''; } /** * This function does not really render an index but inserts a placeholder. * * @return string * @see ODTDocument::insertIndex for API wrapper function * @see ODTIndex::insertIndex for more information */ function render_index($type='toc', $settings=NULL) { $data = array(); $data = $this->get_index_settings($type, $settings); $this->document->insertIndex($type, $data); return ''; } /** * This function detmerines the settings for a TOC or chapter index. * The layout settings are taken from the configuration and $settings. * The result is returned as an array. * * $settings can include the following options syntax: * - Title e.g. 'title=Example;'. * Default is 'Table of Contents' (for english, see language files for other languages default value). * - Leader sign, e.g. 'leader-sign=.;'. * Default is '.'. * - Indents (in cm), e.g. 'indents=indents=0,0.5,1,1.5,2,2.5,3;'. * Default is 0.5 cm indent more per level. * - Maximum outline/TOC level, e.g. 'maxtoclevel=5;'. * Default is taken from DokuWiki config setting 'maxtoclevel'. * - Insert pagebreak after TOC, e.g. 'pagebreak=1;'. * Default is '1', means insert pagebreak after TOC. * - Set style per outline/TOC level, e.g. 'styleL2="color:red;font-weight:900;";'. * Default is 'color:black'. * * It is allowed to use defaults for all settings by omitting $settings. * Multiple settings can be combined, e.g. 'leader-sign=.;indents=0,0.5,1,1.5,2,2.5,3;'. */ protected function get_index_settings($type, $settings) { $matches = array(); $data = array(); $data ['numbered_headings'] = false; if ($this->config->getParam('outline_list_style') == 'Numbers') { $data ['numbered_headings'] = true; } // It seems to be not supported in ODT to have a different start // outline level than 1. $data ['maxlevel'] = $this->config->getParam('toc_maxlevel'); if ( preg_match('/maxlevel=[^;]+;/', $settings, $matches) === 1 ) { $temp = substr ($matches [0], 9); $temp = trim ($temp, ';'); $data ['maxlevel'] = $temp; } // Determine title, default for table of contents is 'Table of Contents'. // Default for chapter index is empty. // Syntax for 'Test' as title would be "title=test;". $data ['title'] = ''; if ($type == 'toc') { $data ['title'] = $this->getLang('toc_title'); } if ( preg_match('/title=[^;]+;/', $settings, $matches) === 1 ) { $temp = substr ($matches [0], 6); $temp = trim ($temp, ';'); $data ['title'] = $temp; } // Determine leader-sign, default is '.'. // Syntax for '.' as leader-sign would be "leader_sign=.;". $data ['leader_sign'] = $this->config->getParam('toc_leader_sign'); if ( preg_match('/leader_sign=[^;]+;/', $settings, $matches) === 1 ) { $temp = substr ($matches [0], 12); $temp = trim ($temp, ';'); $data ['leader_sign'] = $temp [0]; } // Determine indents, default is '0.5' (cm) per level. // Syntax for a indent of '0.5' for 5 levels would be "indents=0,0.5,1,1.5,2;". // The values are absolute for each level, not relative to the higher level. $data ['indents'] = explode (',', $this->config->getParam('toc_indents')); if ( preg_match('/indents=[^;]+;/', $settings, $matches) === 1 ) { $temp = substr ($matches [0], 8); $temp = trim ($temp, ';'); $data ['indents'] = explode (',', $temp); } // Determine pagebreak, default is on '1'. // Syntax for pagebreak off would be "pagebreak=0;". $data ['pagebreak'] = $this->config->getParam('toc_pagebreak'); if ( preg_match('/pagebreak=[^;]+;/', $settings, $matches) === 1 ) { $temp = substr ($matches [0], 10); $temp = trim ($temp, ';'); $data ['pagebreak'] = 'false'; if ( $temp == '1' ) { $data ['pagebreak'] = 'true'; } else if ( strcasecmp($temp, 'true') == 0 ) { $data ['pagebreak'] = 'true'; } } // Determine text style for the index heading. $data ['style_heading'] = NULL; if ( preg_match('/styleH="[^"]+";/', $settings, $matches) === 1 ) { $quote = strpos ($matches [0], '"'); $temp = substr ($matches [0], $quote+1); $temp = trim ($temp, '";'); $data ['style_heading'] = $temp.';'; } // Determine text styles per level. // Syntax for a style level 1 is "styleL1="color:black;"". // The default style is just 'color:black;'. for ( $count = 0 ; $count < $data ['maxlevel'] ; $count++ ) { $data ['styleL'.($count + 1)] = $this->config->getParam('toc_style'); if ( preg_match('/styleL'.($count + 1).'="[^"]+";/', $settings, $matches) === 1 ) { $quote = strpos ($matches [0], '"'); $temp = substr ($matches [0], $quote+1); $temp = trim ($temp, '";'); $data ['styleL'.($count + 1)] = $temp.';'; } } return $data; } /** * Add an item to the TOC * (Dummy function required by the Doku_Renderer class) * * @param string $id the hash link * @param string $text the text to display * @param int $level the nesting level */ function toc_additem($id, $text, $level) {} /** * Return total page width in centimeters * (margins are included) * * @see ODTDocument::getWidth for API wrapper function * @see pageFormat::getWidth for more information * @author LarsDW223 */ function _getPageWidth(){ return $this->document->getWidth(); } /** * Return total page height in centimeters * (margins are included) * * @see ODTDocument::getHeight for API wrapper function * @see pageFormat::getHeight for more information * @author LarsDW223 */ function _getPageHeight(){ return $this->document->getHeight(); } /** * Return left margin in centimeters * * @see ODTDocument::getMarginLeft for API wrapper function * @see pageFormat::getMarginLeft for more information * @author LarsDW223 */ function _getLeftMargin(){ return $this->document->getMarginLeft(); } /** * Return right margin in centimeters * * @see ODTDocument::getMarginRight for API wrapper function * @see pageFormat::getMarginRight for more information * @author LarsDW223 */ function _getRightMargin(){ return $this->document->getMarginRight(); } /** * Return top margin in centimeters * * @see ODTDocument::getMarginTop for API wrapper function * @see pageFormat::getMarginTop for more information * @author LarsDW223 */ function _getTopMargin(){ return $this->document->getMarginTop(); } /** * Return bottom margin in centimeters * * @see ODTDocument::getMarginBottom for API wrapper function * @see pageFormat::getMarginBottom for more information * @author LarsDW223 */ function _getBottomMargin(){ return $this->document->getMarginBottom(); } /** * Return width percentage value if margins are taken into account. * Usually "100%" means 21cm in case of A4 format. * But usually you like to take care of margins. This function * adjusts the percentage to the value which should be used for margins. * So 100% == 21cm e.g. becomes 80.9% == 17cm (assuming a margin of 2 cm on both sides). * * @param int|string $percentage * @return int|string * * @see ODTDocument::getRelWidthMindMargins for API wrapper function * @see pageFormat::getRelWidthMindMargins for more information * @author LarsDW223 */ function _getRelWidthMindMargins ($percentage = '100'){ return $this->document->getRelWidthMindMargins($percentage); } /** * Like _getRelWidthMindMargins but returns the absulute width * in centimeters. * * @param string|int|float $percentage * @return float * * @see ODTDocument::getAbsWidthMindMargins for API wrapper function * @see pageFormat::getAbsWidthMindMargins for more information * @author LarsDW223 */ function _getAbsWidthMindMargins ($percentage = '100'){ return $this->document->getAbsWidthMindMargins($percentage); } /** * Return height percentage value if margins are taken into account. * Usually "100%" means 29.7cm in case of A4 format. * But usually you like to take care of margins. This function * adjusts the percentage to the value which should be used for margins. * So 100% == 29.7cm e.g. becomes 86.5% == 25.7cm (assuming a margin of 2 cm on top and bottom). * * @param string|float|int $percentage * @return float|string * * @see ODTDocument::getRelHeightMindMargins for API wrapper function * @see pageFormat::getRelHeightMindMargins for more information * @author LarsDW223 */ function _getRelHeightMindMargins ($percentage = '100'){ return $this->document->getRelHeightMindMargins($percentage); } /** * Like _getRelHeightMindMargins but returns the absulute width * in centimeters. * * @param string|int|float $percentage * @return float * * @see ODTDocument::getAbsHeightMindMargins for API wrapper function * @see pageFormat::getAbsHeightMindMargins for more information * @author LarsDW223 */ function _getAbsHeightMindMargins ($percentage = '100'){ return $this->document->getAbsHeightMindMargins($percentage); } /** * Render plain text data. * * @param string $text * @see ODTDocument::addPlainText for more information */ function cdata($text) { $this->document->addPlainText($text); } /** * Open a paragraph. * * @param string $style Name of the style to use for the paragraph * * @see ODTDocument::paragraphOpen for API wrapper function * @see ODTParagraph::paragraphOpen for more information */ function p_open($style=NULL){ $this->document->paragraphOpen($style); } /** * Close a paragraph. * * @see ODTDocument::paragraphClose for API wrapper function * @see ODTParagraph::paragraphClose for more information */ function p_close(){ $this->document->paragraphClose(); } /** * Set bookmark for the start of the page. This just saves the title temporarily. * It is then to be inserted in the first header or paragraph. * * @param string $id ID of the bookmark */ function set_page_bookmark($id){ $this->document->setPageBookmark($id); } /** * Render a heading * * @param string $text the text to display * @param int $level header level * @param int $pos byte position in the original source */ function header($text, $level, $pos){ $this->document->heading($text, $level); } function hr() { $this->document->horizontalRule(); } function linebreak() { $this->document->linebreak(); } function pagebreak() { $this->document->pagebreak(); } function strong_open() { $this->document->spanOpen($this->document->getStyleName('strong')); } function strong_close() { $this->document->spanClose(); } function emphasis_open() { $this->document->spanOpen($this->document->getStyleName('emphasis')); } function emphasis_close() { $this->document->spanClose(); } function underline_open() { $this->document->spanOpen($this->document->getStyleName('underline')); } function underline_close() { $this->document->spanClose(); } function monospace_open() { $this->document->spanOpen($this->document->getStyleName('monospace')); } function monospace_close() { $this->document->spanClose(); } function subscript_open() { $this->document->spanOpen($this->document->getStyleName('sub')); } function subscript_close() { $this->document->spanClose(); } function superscript_open() { $this->document->spanOpen($this->document->getStyleName('sup')); } function superscript_close() { $this->document->spanClose(); } function deleted_open() { $this->document->spanOpen($this->document->getStyleName('del')); } function deleted_close() { $this->document->spanClose(); } function generateSpansfromHTMLCode($HTMLCode){ $this->document->generateSpansfromHTMLCode($HTMLCode); } /* * Tables */ /** * Start a table * * @param int $maxcols maximum number of columns * @param int $numrows NOT IMPLEMENTED */ function table_open($maxcols = NULL, $numrows = NULL, $pos = NULL){ $this->document->tableOpen($maxcols, $numrows); } function table_close($pos = NULL){ $this->document->tableClose(); } function tablecolumn_add(){ $this->document->tableAddColumn(); } function tablerow_open(){ $this->document->tableRowOpen(); } function tablerow_close(){ $this->document->tableRowClose(); } /** * Open a table header cell * * @param int $colspan * @param string $align left|center|right * @param int $rowspan */ function tableheader_open($colspan = 1, $align = "left", $rowspan = 1){ $this->document->tableHeaderOpen($colspan, $rowspan, $align); } function tableheader_close(){ $this->document->tableHeaderClose(); } /** * Open a table cell * * @param int $colspan * @param string $align left|center|right * @param int $rowspan */ function tablecell_open($colspan = 1, $align = "left", $rowspan = 1){ $this->document->tableCellOpen($colspan, $rowspan, $align); } function tablecell_close(){ $this->document->tableCellClose(); } /** * Callback for footnote start syntax. * * @author Andreas Gohr */ function footnote_open() { $this->document->footnoteOpen(); } /** * Callback for footnote end syntax. * * @author Andreas Gohr */ function footnote_close() { $this->document->footnoteClose(); } function listu_open($continue=false) { $this->document->listOpen($continue, $this->document->getStyleName('list'), 'ul'); } function listu_close() { $this->document->listClose(); } function listo_open($continue=false) { $this->document->listOpen($continue, $this->document->getStyleName('numbering'), 'ol'); } function listo_close() { $this->document->listClose(); } function list_close() { $this->document->listClose(); } /** * Open a list item * * @param int $level the nesting level */ function listitem_open($level, $node = false) { $this->document->listItemOpen($level); } function listitem_close() { $this->document->listItemClose(); } /** * Open a list header * * @param int $level the nesting level */ function listheader_open($level) { $this->document->listHeaderOpen($level); } function listheader_close() { $this->document->listHeaderClose(); } function listcontent_open() { $this->document->listContentOpen(); } function listcontent_close() { $this->document->listContentClose(); } /** * Output unformatted $text * * @param string $text */ function unformatted($text) { $this->document->addPlainText($text); } /** * Format an acronym * * @param string $acronym */ function acronym($acronym) { $this->document->addPlainText($acronym); } /** * @param string $smiley */ function smiley($smiley) { if ( array_key_exists($smiley, $this->smileys) ) { $src = DOKU_INC."lib/images/smileys/".$this->smileys[$smiley]; $this->_odtAddImage($src); } else { $this->document->addPlainText($smiley); } } /** * Format an entity * * @param string $entity */ function entity($entity) { if (array_key_exists($entity, $this->entities)) { $entity = $this->entities[$entity]; } // Add plain text will replace XML entities $this->document->addPlainText($entity); } /** * Typographically format a multiply sign * * Example: ($x=640, $y=480) should result in "640×480" * * @param string|int $x first value * @param string|int $y second value */ function multiplyentity($x, $y) { $text .= $x.'×'.$y; $this->document->addPlainText($text); } function singlequoteopening() { global $lang; $text .= $lang['singlequoteopening']; $this->document->addPlainText($text); } function singlequoteclosing() { global $lang; $text .= $lang['singlequoteclosing']; $this->document->addPlainText($text); } function apostrophe() { global $lang; $text .= $lang['apostrophe']; $this->document->addPlainText($text); } function doublequoteopening() { global $lang; $text .= $lang['doublequoteopening']; $this->document->addPlainText($text); } function doublequoteclosing() { global $lang; $text .= $lang['doublequoteclosing']; $this->document->addPlainText($text); } /** * Output inline PHP code * * @param string $text The PHP code */ function php($text) { $this->monospace_open(); $this->document->addPlainText($text); $this->monospace_close(); } /** * Output block level PHP code * * @param string $text The PHP code */ function phpblock($text) { $this->file($text); } /** * Output raw inline HTML * * @param string $text The HTML */ function html($text) { $this->monospace_open(); $this->document->addPlainText($text); $this->monospace_close(); } /** * Output raw block-level HTML * * @param string $text The HTML */ function htmlblock($text) { $this->file($text); } /** * Output preformatted text * * @param string $text */ function preformatted($text) { $this->_preformatted($text); } /** * Display text as file content, optionally syntax highlighted * * @param string $text text to show * @param string $language programming language to use for syntax highlighting * @param string $filename file path label */ function file($text, $language=null, $filename=null, $options=null) { $this->_highlight('file', $text, $language, $options); } function quote_open() { $this->document->quoteOpen(); } function quote_close() { $this->document->quoteClose(); } /** * Display text as code content, optionally syntax highlighted * * @param string $text text to show * @param string $language programming language to use for syntax highlighting * @param string $filename file path label */ function code($text, $language=null, $filename=null, $options=null) { $this->_highlight('code', $text, $language, $options); } /** * @param string $text * @param string $style * @param bool $notescaped */ function _preformatted($text, $style=null, $notescaped=true) { $this->document->addPreformattedText($text, $style, $notescaped); } /** * This function creates the styles required for Geshi-Syntax highlighting. * We need two non-standard-ODT-Plugin-styles: * Paragraph-Style: We need a paragraph style without top and bottom margin. * Otherwise there would be a sapce betwwen the source code lines. * List-Style: Usually lists are indented. Our list shall not be indented. * (A list will only be created by Geshi if line numbering is enabled) */ protected function createGeshiListStyle () { $style_name = 'highlight_list_paragraph_style'; if (!$this->document->styleExists($style_name)) { // For the list paragrpah copy body style and remove margins $body = $this->document->getStyleName('body'); $style = clone($this->document->getStyle($body)); if (isset($style)) { $style->setProperty('style-name', $style_name); $style->setProperty('margin-top', NULL); $style->setProperty('margin-bottom', NULL); $this->document->addAutomaticStyle($style); } } $style_name = 'highlight_list_numbers_text_style'; if (!$this->document->styleExists($style_name)) { $source_code_style = $this->document->getStyleByAlias('source code'); $properties = array(); $properties ['style-name'] = $style_name; $properties ['style-display-name'] = 'Source Code Numbers style'; $properties ['color'] = $source_code_style->getProperty('color'); if (empty($properties ['color'])) { $properties ['color'] = '#000000'; } $this->document->createTextStyle ($properties, true); } $style_name = 'highlight_list_ol_style'; if (!$this->document->styleExists($style_name)) { // For the list style copy numbering list style and // set indentation for level 1 to '0cm' $ol = $this->document->getStyleName('numbering'); $style = clone($this->document->getStyle($ol)); if (isset($style)) { $style->setProperty('style-name', $style_name); $style->setPropertyForLevel(1, 'text-style-name', 'highlight_list_numbers_text_style'); $style->setPropertyForLevel(1, 'text-align', 'left'); $style->setPropertyForLevel(1, 'list-level-position-and-space-mode', 'label-alignment'); $style->setPropertyForLevel(1, 'label-followed-by', 'listtab'); $style->setPropertyForLevel(1, 'list-tab-stop-position', '1cm'); $style->setPropertyForLevel(1, 'text-indent', '-1cm'); $style->setPropertyForLevel(1, 'margin-left', '1cm'); $this->document->addAutomaticStyle($style); } } } /** * @param string $type * @param string $text * @param string $language */ function _highlight($type, $text, $language=null, $options = null) { if (is_null($language)) { $this->_preformatted($text, $style_name); return; } // Use cached geshi $highlighted_code = p_xhtml_cached_geshi($text, $language, '', $options); // Create Geshi styles required for ODT and get ODT sourcecode style $this->createGeshiListStyle (); $source_code_style = $this->document->getStyleByAlias('source code'); $options = array(); $options ['escape_content'] = 'false'; $options ['space'] = 'preserve'; $options ['media_selector'] = 'screen'; $options ['element'] = 'pre'; $options ['style_names'] = 'prefix_and_class'; $options ['style_names_prefix'] = 'highlight_'; if (empty($language)) { $options ['attributes'] = 'class="code"'; } else { $options ['attributes'] = 'class="code '.$language.'"'; } $options ['list_ol_style'] = 'highlight_list_ol_style'; $options ['list_p_style'] = 'highlight_list_paragraph_style'; $options ['p_style'] = $this->document->getStyleName('preformatted'); // Open table with just one cell $this->document->tableOpen(); $this->document->tableRowOpen(); $properties = array(); $properties ['border'] = $source_code_style->getProperty('border'); $properties ['border-top'] = $source_code_style->getProperty('border-top'); $properties ['border-right'] = $source_code_style->getProperty('border-right'); $properties ['border-bottom'] = $source_code_style->getProperty('border-bottom'); $properties ['border-left'] = $source_code_style->getProperty('border-left'); $properties ['padding'] = $source_code_style->getProperty('padding'); $properties ['padding-top'] = $source_code_style->getProperty('padding-top'); $properties ['padding-right'] = $source_code_style->getProperty('padding-right'); $properties ['padding-bottom'] = $source_code_style->getProperty('padding-bottom'); $properties ['padding-left'] = $source_code_style->getProperty('padding-left'); $properties ['background-color'] = $source_code_style->getProperty('background-color'); $this->document->tableCellOpenUseProperties($properties); // Generate ODT content from Geshi's HTML code $this->document->generateODTfromHTMLCode($highlighted_code, $options); // Close table $this->document->tableCellClose(); $this->document->tableRowClose(); $this->document->tableClose(); } /** * Render an internal media file * * @param string $src media ID * @param string $title descriptive text * @param string $align left|center|right * @param int $width width of media in pixel * @param int $height height of media in pixel * @param string $cache cache|recache|nocache * @param string $linking linkonly|detail|nolink * @param bool $returnonly whether to return odt or write to doc attribute */ function internalmedia ($src, $title=NULL, $align=NULL, $width=NULL, $height=NULL, $cache=NULL, $linking=NULL, $returnonly = false) { global $ID; resolve_mediaid(getNS($ID),$src, $exists); list(/* $ext */,$mime) = mimetype($src); if ($linking == 'linkonly') { $url = str_replace('doku.php?id=','lib/exe/fetch.php?media=',wl($src,'',true)); if (empty($title)) { $title = $src; } if ($returnonly) { return $this->externallink($url, $title, true); } else { $this->externallink($url, $title); } return; } if(substr($mime,0,5) == 'image'){ $file = mediaFN($src); if($returnonly) { return $this->_odtAddImage($file, $width, $height, $align, $title, NULL, true); } else { $this->_odtAddImage($file, $width, $height, $align, $title); } }else{ /* // FIXME build absolute medialink and call externallink() $this->code('FIXME internalmedia: '.$src); */ //FIX by EPO/Intersel - create a link to the dokuwiki internal resource if (empty($title)) {$title=explode(':',$src); $title=end($title);} if($returnonly) { return $this->externalmedia(str_replace('doku.php?id=','lib/exe/fetch.php?media=',wl($src,'',true)),$title, null, null, null, null, null, true); } else { $this->externalmedia(str_replace('doku.php?id=','lib/exe/fetch.php?media=',wl($src,'',true)),$title, null, null, null, null, null); } //End of FIX } } /** * Render an external media file * * @param string $src full media URL * @param string $title descriptive text * @param string $align left|center|right * @param int $width width of media in pixel * @param int $height height of media in pixel * @param string $cache cache|recache|nocache * @param string $linking linkonly|detail|nolink * @param bool $returnonly whether to return odt or write to doc attribute */ function externalmedia ($src, $title=NULL, $align=NULL, $width=NULL, $height=NULL, $cache=NULL, $linking=NULL, $returnonly = false) { list($ext,$mime) = mimetype($src); if ($linking == 'linkonly') { $url = $src; if (empty($title)) { $title = $src; } if ($returnonly) { return $this->externallink($url, $title, true); } else { $this->externallink($url, $title); } return; } if(substr($mime,0,5) == 'image'){ $tmp_dir = $this->config->getParam ('tmpdir')."/odt"; $tmp_name = $tmp_dir."/".md5($src).'.'.$ext; $client = new DokuHTTPClient; $img = $client->get($src); if ($img === FALSE) { $tmp_name = $src; // fallback to a simple link } else { if (!is_dir($tmp_dir)) io_mkdir_p($tmp_dir); $tmp_img = fopen($tmp_name, "w") or die("Can't create temp file $tmp_img"); fwrite($tmp_img, $img); fclose($tmp_img); } $doc = ''; if ($linking != 'nolink') { $doc .= $this->document->openImageLink ($src, $returnonly); } $doc .= $this->_odtAddImage($tmp_name, $width, $height, $align, $title, $returnonly); if ($linking != 'nolink') { $doc .= $this->document->closeImageLink ($returnonly); } if (file_exists($tmp_name)) unlink($tmp_name); return $doc; }else{ if($returnonly) { return $this->externallink($src,$title,true); } else { $this->externallink($src,$title); } } } /** * Render a CamelCase link * * @param string $link The link name * @param bool $returnonly whether to return odt or write to doc attribute * @see http://en.wikipedia.org/wiki/CamelCase */ function camelcaselink($link, $returnonly = false) { if($returnonly) { return $this->internallink($link,$link, null, true); } else { $this->internallink($link, $link); } } /** * This function is only used for the DokuWiki specific * 'returnonly' behaviour. * * @param string $id * @param string $name */ function reference($id, $name = NULL) { $ret = '_xmlEntities($name).''; } else { $ret .= '/>'; } return $ret; } /** * Render a wiki internal link * * @param string $id page ID to link to. eg. 'wiki:syntax' * @param string|array $name name for the link, array for media file * @param bool $returnonly whether to return odt or write to doc attribute * * @author Andreas Gohr */ function internallink($id, $name = NULL, $returnonly = false) { global $ID; // default name is based on $id as given $default = $this->_simpleTitle($id); // now first resolve and clean up the $id resolve_pageid(getNS($ID),$id,$exists); $name = $this->_getLinkTitle($name, $default, $isImage, $id); // build the absolute URL (keeping a hash if any) list($id,$hash) = explode('#',$id,2); $url = wl($id,'',true); if($hash) $url .='#'.$hash; if ($ID == $id) { if ($hash) { $id = $hash; } if($returnonly) { return $this->locallink_with_text($hash, $id, $name, $returnonly); } else { $this->locallink_with_text($hash, $id, $name, $returnonly); } } else { if($returnonly) { return $this->_doLink($url, $name, $returnonly); } else { $this->_doLink($url, $name, $returnonly); } } } /** * Add external link * * @param string $url full URL with scheme * @param string|array $name name for the link, array for media file * @param bool $returnonly whether to return odt or write to doc attribute */ function externallink($url, $name = NULL, $returnonly = false) { $name = $this->_getLinkTitle($name, $url, $isImage); if($returnonly) { return $this->_doLink($url, $name, $returnonly); } else { $this->_doLink($url, $name, $returnonly); } } /** * Inserts a local link with text. * * @fixme add image handling * * @param string $hash hash link identifier * @param string $id name for the link (the reference) * @param string $text text for the link (text inserted instead of reference) */ function locallink_with_text($hash, $id = NULL, $text = NULL, $returnonly = false){ if (!$returnonly) { $id = $this->_getLinkTitle($id, $hash, $isImage); $this->document->insertCrossReference($id, $text); } else { return reference($hash, $name); } } /** * Inserts a local link. * * @fixme add image handling * * @param string $hash hash link identifier * @param string $name name for the link */ function locallink($hash, $name = NULL){ $name = $this->_getLinkTitle($name, $hash, $isImage); $this->document->insertCrossReference($hash, $name); } /** * Render an interwiki link * * You may want to use $this->_resolveInterWiki() here * * @param string $match original link - probably not much use * @param string|array $name name for the link, array for media file * @param string $wikiName indentifier (shortcut) for the remote wiki * @param string $wikiUri the fragment parsed from the original link * @param bool $returnonly whether to return odt or write to doc attribute */ function interwikilink($match, $name = NULL, $wikiName, $wikiUri, $returnonly = false) { $name = $this->_getLinkTitle($name, $wikiUri, $isImage); $url = $this-> _resolveInterWiki($wikiName,$wikiUri); if($returnonly) { return $this->_doLink($url, $name, $returnonly); } else { $this->_doLink($url, $name, $returnonly); } } /** * Just print WindowsShare links * * @fixme add image handling * * @param string $url the link * @param string|array $name name for the link, array for media file * @param bool $returnonly whether to return odt or write to doc attribute */ function windowssharelink($url, $name = NULL, $returnonly = false) { $name = $this->_getLinkTitle($name, $url, $isImage); if($returnonly) { return $name; } else { $this->document->addPlainText($name); } } /** * Just print email links * * @fixme add image handling * * @param string $address Email-Address * @param string|array $name name for the link, array for media file * @param bool $returnonly whether to return odt or write to doc attribute */ function emaillink($address, $name = NULL, $returnonly = false) { $name = $this->_getLinkTitle($name, $address, $isImage); if($returnonly) { return $this->_doLink("mailto:".$address, $name, $returnonly); } else { $this->_doLink("mailto:".$address, $name, $returnonly); } } /** * Add a hyperlink, handling Images correctly * * @author Andreas Gohr * * @param string $url * @param string|array $name */ function _doLink($url,$name, $returnonly = false){ $url = $this->_xmlEntities($url); $doc = ''; if(is_array($name)){ // Images $doc .= $this->document->openImageLink ($url, $returnonly); if($name['type'] == 'internalmedia'){ $doc .= $this->internalmedia($name['src'], $name['title'], $name['align'], $name['width'], $name['height'], $name['cache'], $name['linking'], $returnonly); } $doc .= $this->document->closeImageLink ($returnonly); }else{ // Text $doc .= $this->document->insertHyperlink ($url, $name, NULL, NULL, $returnonly); } return $doc; } /** * Construct a title and handle images in titles * * @author Harry Fuecks * * @param string|array|null $title * @param string $default * @param bool|null $isImage * @param string $id * @return mixed */ function _getLinkTitle($title, $default, & $isImage, $id=null) { $isImage = false; if ( is_array($title) ) { $isImage = true; return $title; } elseif (is_null($title) || trim($title) == '') { if ($this->config->getParam ('useheading') && $id) { $heading = p_get_first_heading($id); if ($heading) { return $this->_xmlEntities($heading); } } return $this->_xmlEntities($default); } else { return $this->_xmlEntities($title); } } /** * @param string $value * @return string */ function _xmlEntities($value) { return str_replace( array('&','"',"'",'<','>'), array('&','"',''','<','>'), $value); } /** * Render the output of an RSS feed * * @param string $url URL of the feed * @param array $params Finetuning of the output */ function rss ($url,$params){ global $lang; require_once(DOKU_INC . 'inc/FeedParser.php'); $feed = new FeedParser(); $feed->feed_url($url); //disable warning while fetching $elvl = null; if (!defined('DOKU_E_LEVEL')) { $elvl = error_reporting(E_ERROR); } $rc = $feed->init(); if (!defined('DOKU_E_LEVEL')) { error_reporting($elvl); } //decide on start and end if($params['reverse']){ $mod = -1; $start = $feed->get_item_quantity()-1; $end = $start - ($params['max']); $end = ($end < -1) ? -1 : $end; }else{ $mod = 1; $start = 0; $end = $feed->get_item_quantity(); $end = ($end > $params['max']) ? $params['max'] : $end;; } $this->listu_open(); if($rc){ for ($x = $start; $x != $end; $x += $mod) { $item = $feed->get_item($x); $this->document->listItemOpen(0); $this->document->listContentOpen(); $this->externallink($item->get_permalink(), $item->get_title()); if($params['author']){ $author = $item->get_author(0); if($author){ $name = $author->get_name(); if(!$name) $name = $author->get_email(); if($name) $this->cdata(' '.$lang['by'].' '.$name); } } if($params['date']){ $this->cdata(' ('.$item->get_date($this->config->getParam ('dformat')).')'); } if($params['details']){ $this->cdata(strip_tags($item->get_description())); } $this->document->listContentClose(); $this->document->listItemClose(); } }else{ $this->document->listItemOpen(0); $this->document->listContentOpen(); $this->emphasis_open(); $this->cdata($lang['rssfailed']); $this->emphasis_close(); $this->externallink($url); $this->document->listContentClose(); $this->document->listItemClose(); } $this->listu_close(); } /** * Adds the content of $string as a SVG picture to the document. * * @see ODTDocument::addStringAsSVGImage for API wrapper function * @see ODTImage::addStringAsSVGImage for a detailed description */ function _addStringAsSVGImage($string, $width = NULL, $height = NULL, $align = NULL, $title = NULL, $style = NULL) { $this->document->addStringAsSVGImage($string, $width, $height, $align, $title, $style); } /** * The function adds $string as an SVG image file. * It does NOT insert the image in the document. * * @see ODTDocument::addStringAsSVGImageFile for a detailed description * @see ODTImage::addStringAsSVGImageFile for a detailed description */ function _addStringAsSVGImageFile($string) { return $this->document->addStringAsSVGImageFile($string); } /** * Adds the image $src as a picture file without adding it to the content * of the document. The link name which can be used for the ODT draw:image xlink:href * is returned. The caller is responsible for creating the frame and image tag * but therefore has full control over it. This means he can also set parameters * in the odt frame and image tag which can not be changed using the function _odtAddImage. * * @author LarsDW223 * * @param string $src * @return string */ function _odtAddImageAsFileOnly($src){ return $this->document->addFileAsPicture($src); } /** * Adds an image $src to the document. * * @param string $src The path to the image file * @param string $width Width of the picture (NULL=original size) * @param string $height Height of the picture (NULL=original size) * @param string $align Alignment * @param string $title Title * @param string $style Optional "draw:style-name" * @param boolean $returnonly Only return code * * @see ODTDocument::addImage for API wrapper function * @see ODTImage::addImage for a detailed description */ function _odtAddImage($src, $width = NULL, $height = NULL, $align = NULL, $title = NULL, $style = NULL, $returnonly = false){ if ($returnonly) { return $this->document->addImage($src, $width, $height, $align, $title, $style, $returnonly); } else { $this->document->addImage($src, $width, $height, $align, $title, $style, $returnonly); } } /** * Adds an image $src to the document using the parameters set in $properties. * * @param string $src The path to the image file * @param array $properties Properties (width, height... see ODTImage::addImageUseProperties) * @param boolean $returnonly Only return code * * @see ODTDocument::addImageUseProperties for API wrapper function * @see ODTImage::addImageUseProperties for a detailed description */ function _odtAddImageUseProperties($src, array $properties, $returnonly = false){ if ($returnonly) { return $this->document->addImageUseProperties($src, $properties, $returnonly); } else { $this->document->addImageUseProperties($src, $properties, $returnonly); } } /** * The function tries to examine the width and height * of the image stored in file $src. * * @see ODTDocument::getImageSize for API wrapper function * @see ODTUtility::getImageSize for a detailed description */ public function _odtGetImageSize($src, $maxwidth=NULL, $maxheight=NULL){ return $this->document->getImageSize($src, $maxwidth, $maxheight); } /** * @param string $src * @param $width * @param $height * @return array */ function _odtGetImageSizeString($src, $width = NULL, $height = NULL){ return $this->document->getImageSizeString($src, $width, $height); } /** * Open a span using CSS. * * @see ODTDocument::spanOpenUseCSS for API wrapper function * @see ODTSpan::spanOpenUseCSS for detailed documentation * @author LarsDW223 */ function _odtSpanOpenUseCSS($element=NULL, $attributes=NULL, cssimportnew $import=NULL){ $this->document->spanOpenUseCSS($element, $attributes, $import); } /** * Open a span using properties. * * @see ODTDocument::spanOpenUseProperties for API wrapper function * @see ODTSpan::spanOpenUseProperties for detailed documentation * @author LarsDW223 */ function _odtSpanOpenUseProperties($properties){ $this->document->spanOpenUseProperties($properties); } function _odtSpanOpen($style_name){ $this->document->spanOpen($style_name); } /** * This function closes a span (previously opened with _odtSpanOpenUseCSS). * * @author LarsDW223 */ function _odtSpanClose(){ $this->document->spanClose(); } /** * Open a paragraph using CSS. * * @see ODTDocument::paragraphOpenUseCSS for API wrapper function * @see ODTParagraph::paragraphOpenUseCSS for detailed documentation * @author LarsDW223 */ function _odtParagraphOpenUseCSS($element=NULL, $attributes=NULL, cssimportnew $import=NULL){ $this->document->paragraphOpenUseCSS($element, $attributes, $import); } /** * Open a paragraph using properties. * * @see ODTDocument::paragraphOpenUseProperties for API wrapper function * @see ODTParagraph::paragraphOpenUseProperties for detailed documentation * @author LarsDW223 */ function _odtParagraphOpenUseProperties($properties){ $this->document->paragraphOpenUseProperties($properties); } /** * Open a text box using CSS. * * @see ODTDocument::openTextBoxUseCSS for API wrapper function * @see ODTFrame::openTextBoxUseCSS for detailed documentation */ function _odtOpenTextBoxUseCSS ($element=NULL, $attributes=NULL, cssimportnew $import=NULL) { $this->document->openTextBoxUseCSS ($element, $attributes, $import); } /** * This function opens a div. As divs are not supported by ODT, it will be exported as a frame. * To be more precise, to frames will be created. One including a picture nad the other including the text. * A picture frame will only be created if a 'background-image' is set in the CSS style. * * The currently supported CSS properties are: * background-color, color, padding, margin, display, border-radius, min-height. * The background-image is simulated using a picture frame. * FIXME: Find a way to successfuly use the background-image in the graphic style (see comments). * * The div should be closed by calling '_odtDivCloseAsFrame'. * * @author LarsDW223 * * @param array $properties */ function _odtDivOpenAsFrameUseProperties ($properties) { dbg_deprecated('_odtOpenTextBoxUseProperties'); $this->_odtOpenTextBoxUseProperties ($properties); } /** * This function closes a div/frame (previously opened with _odtDivOpenAsFrameUseCSS). * * @author LarsDW223 */ function _odtDivCloseAsFrame () { $this->_odtCloseTextBox(); } /** * This function opens a new table using CSS. * * @author LarsDW223 * @see ODTDocument::tableOpenUseCSS for API wrapper function * @see ODTTable::tableOpenUseCSS for detailed documentation */ function _odtTableOpenUseCSS($maxcols = NULL, $numrows = NULL, $element=NULL, $attributes = NULL, cssimportnew $import = NULL){ $this->document->tableOpenUseCSS($maxcols, $numrows, $element, $attributes, $import); } /** * This function opens a new table using properties. * * @author LarsDW223 * @see ODTDocument::tableOpenUseProperties for API wrapper function * @see ODTTable::tableOpenUseProperties for detailed documentation */ function _odtTableOpenUseProperties ($properties, $maxcols = 0, $numrows = 0){ $this->document->tableOpenUseProperties ($properties, $maxcols, $numrows); } /** * This function closes a table. * * @author LarsDW223 * @see ODTDocument::tableClose for API wrapper function * @see ODTTable::tableClose for detailed documentation */ function _odtTableClose () { $this->document->tableClose(); } /** * This function adds a new table column using properties. * * @author LarsDW223 * @see ODTDocument::tableAddColumnUseProperties for API wrapper function * @see ODTTable::tableAddColumnUseProperties for detailed documentation */ function _odtTableAddColumnUseProperties (array $properties = NULL){ $this->document->tableAddColumnUseProperties($properties); } /** * This function opens a new table header using CSS. * The header should be closed by calling 'tableheader_close()'. * * @author LarsDW223 * @see ODTDocument::tableHeaderOpenUseCSS for API wrapper function * @see ODTTable::tableHeaderOpenUseCSS for detailed documentation */ function _odtTableHeaderOpenUseCSS($colspan = 1, $rowspan = 1, $element=NULL, $attributes=NULL, cssimportnew $import=NULL){ $this->document->tableHeaderOpenUseCSS($colspan, $rowspan, $element, $attributes, $import); } /** * This function opens a new table header using properties. * The header should be closed by calling 'tableheader_close()'. * * @author LarsDW223 * @see ODTDocument::tableHeaderOpenUseProperties for API wrapper function * @see ODTTable::tableHeaderOpenUseProperties for detailed documentation */ function _odtTableHeaderOpenUseProperties ($properties = NULL, $colspan = 1, $rowspan = 1){ $this->document->tableHeaderOpenUseProperties($properties, $colspan = 1, $rowspan = 1); } /** * This function opens a new table row using CSS. * The row should be closed by calling 'tablerow_close()'. * * @author LarsDW223 * @see ODTDocument::tableRowOpenUseCSS for API wrapper function * @see ODTTable::tableRowOpenUseCSS for detailed documentation */ function _odtTableRowOpenUseCSS($element=NULL, $attributes=NULL, cssimportnew $import=NULL){ $this->document->tableRowOpenUseCSS($element, $attributes, $import); } /** * This function opens a new table row using properties. * The row should be closed by calling 'tablerow_close()'. * * @author LarsDW223 * @see ODTDocument::tableRowOpenUseProperties for API wrapper function * @see ODTTable::tableRowOpenUseProperties for detailed documentation */ function _odtTableRowOpenUseProperties ($properties){ $this->document->tableRowOpenUseProperties($properties); } /** * This function opens a new table cell using CSS. * The cell should be closed by calling 'tablecell_close()'. * * @author LarsDW223 * @see ODTDocument::tableCellOpenUseCSS for API wrapper function * @see ODTTable::tableCellOpenUseCSS for detailed documentation */ function _odtTableCellOpenUseCSS($colspan = 1, $rowspan = 1, $element=NULL, $attributes=NULL, cssimportnew $import=NULL){ $this->document->tableCellOpenUseCSS($colspan, $rowspan, $element, $attributes, $import); } /** * This function opens a new table cell using properties. * The cell should be closed by calling 'tablecell_close()'. * * @author LarsDW223 * @see ODTDocument::tableCellOpenUseProperties for API wrapper function * @see ODTTable::tableCellOpenUseProperties for detailed documentation */ function _odtTableCellOpenUseProperties ($properties, $colspan = 1, $rowspan = 1){ $this->document->tableCellOpenUseProperties($properties, $colspan, $rowspan); } /** * Open a multi column text box in a frame using properties. * * @see ODTDocument::openMultiColumnTextBoxUseProperties for API wrapper function * @see ODTFrame::openMultiColumnTextBoxUseProperties for detailed documentation */ function _odtOpenMultiColumnFrame ($properties) { $this->document->openMultiColumnTextBoxUseProperties($properties); } /** * This function closes a multi column frame (previously opened with _odtOpenMultiColumnFrame). * * @see ODTDocument::closeTextBox for API wrapper function * @see ODTFrame::closeTextBox for detailed documentation * @author LarsDW223 */ function _odtCloseMultiColumnFrame () { $this->document->closeMultiColumnTextBox(); } /** * Open a text box in a frame using properties. * * @see ODTDocument::openTextBoxUseProperties for API wrapper function * @see ODTFrame::openTextBoxUseProperties for detailed documentation */ function _odtOpenTextBoxUseProperties ($properties) { $this->document->openTextBoxUseProperties ($properties); } /** * This function closes a textbox. * * @see ODTDocument::closeTextBox for API wrapper function * @see ODTFrame::closeTextBox for detailed documentation * @author LarsDW223 */ function _odtCloseTextBox () { $this->document->closeTextBox(); } /** * Open a frame using properties. * * @see ODTDocument::openFrameUseProperties for API wrapper function * @see ODTFrame::openFrameUseProperties for detailed documentation */ function _odtOpenFrameUseProperties ($properties) { $this->document->openFrameUseProperties ($properties); } /** * This function closes a frame. * * @see ODTDocument::closeFrame for API wrapper function * @see ODTFrame::closeFrame for detailed documentation * @author LarsDW223 */ function _odtCloseFrame () { $this->document->closeFrame(); } /** * @param array $dest * @param $element * @param $classString * @param $inlineStyle */ public function getODTProperties (&$dest, $element, $classString, $inlineStyle, $media_sel=NULL, $cssId=NULL) { if (!isset($media_sel)) { $media_sel = $this->config->getParam ('media_sel'); } // Get properties for our class/element from imported CSS $this->import->getPropertiesForElement($dest, $element, $classString, $media_sel, $cssId); // Interpret and add values from style to our properties $this->document->getCSSStylePropertiesForODT($dest, $inlineStyle); // Adjust values for ODT //foreach ($dest as $property => $value) { // $dest [$property] = $this->adjustValueForODT ($property, $value, 14); //} $this->document->adjustValuesForODT($dest); } /** * Replace a CSS URL value with the given path. * * @param $URL CSS URL e.g. 'url(images/xyz.png);' * @param $replacement The local path * @return string The resulting complete file path */ public function replaceURLPrefix ($URL, $replacement) { return $this->import->replaceURLPrefix ($URL, $replacement); } /** * Convert pixel to points (X axis). * * @param $pixel value to convert * @return float The converted value in points * @see ODTDocument::toPoints for API wrapper function * @see ODTUnits::toPoints for detailed documentation */ public function pixelToPointsX ($pixel) { return $this->document->toPoints($pixel, 'x'); } /** * Convert pixel to points (Y axis). * * @param $pixel value to convert * @return float The converted value in points * @see ODTDocument::toPoints for API wrapper function * @see ODTUnits::toPoints for detailed documentation */ public function pixelToPointsY ($pixel) { return $this->document->toPoints($pixel, 'y'); } /** * Adjust the given property for ODT. * * @param $property The property name * @param $value The property value * @param int $emValue The conversion value for 'em' units * @return string The new, adjusted value * @see ODTUtility::adjustValueForODT for detailed documentation */ public function adjustValueForODT ($property, $value) { return $this->document->adjustValueForODT ($property, $value); } /** * Callback function which adjusts all CSS length values to point. * * @param $property The name of the current CSS property, e.g. 'border-left' * @param $value The current value from the original CSS code * @param $type There are 3 possible values: * - LengthValueXAxis: the property represents a value on the X axis * - LengthValueYAxis: the property represents a value on the Y axis * - CSSValueType::StrokeOrBorderWidth: the property represents a stroke * or border width * @return string The new, adjusted value for the property */ public function adjustLengthCallback ($property, $value, $type) { // Replace px with pt (px does not seem to be supported by ODT) $length = strlen ($value); if ( $length > 2 && $value [$length-2] == 'p' && $value [$length-1] == 'x' ) { $number = trim($value, 'px'); switch ($type) { case CSSValueType::LengthValueXAxis: $adjusted = $this->pixelToPointsX($number).'pt'; break; case CSSValueType::StrokeOrBorderWidth: switch ($property) { case 'border': case 'border-left': case 'border-right': case 'border-top': case 'border-bottom': // border in ODT spans does not support 'px' units, so we convert it. $adjusted = $this->pixelToPointsY($number).'pt'; break; default: $adjusted = $value; break; } break; case CSSValueType::LengthValueYAxis: default: $adjusted = $this->pixelToPointsY($number).'pt'; break; } return $adjusted; } return $value; } /** * This function read the template page and imports all cdata and code content * as additional CSS. ATTENTION: this might overwrite already imported styles * from an ODT or CSS template file. * * @param $pagename The name of the template page */ public function read_templatepage ($pagename) { $instructions = p_cached_instructions(wikiFN($pagename)); $text = ''; foreach($instructions as $instruction) { if($instruction[0] == 'code') { $text .= $instruction[1][0]; } elseif ($instruction[0] == 'cdata') { $text .= $instruction[1][0]; } } $this->document->importCSSFromString ($text, $this->config->getParam('media_sel'), array($this, 'replaceURLPrefixesCallback'), true, $this->config->getParam('olist_label_align')); } /** * Get CSS properties for a given element and adjust them for ODT. * * @see ODTDocument::getODTProperties for more information */ public function getODTPropertiesNew (&$dest, $element, $attributes=NULL, $media_sel=NULL, $inherit=true) { if (!isset($media_sel)) { $media_sel = $this->config->getParam ('media_sel'); } $this->document->getODTProperties ($dest, $element, $attributes, $media_sel, $inherit); } public function getODTPropertiesFromElement (&$dest, iElementCSSMatchable $element, $media_sel=NULL, $inherit=true) { if (!isset($media_sel)) { $media_sel = $this->config->getParam ('media_sel'); } $this->document->getODTPropertiesFromElement ($dest, $element, $media_sel, $inherit); } /** * This function creates a text style. * * @see ODTDocument::createTextStyle for detailed desciption. */ public function createTextStyle ($properties, $common=true) { $this->document->createTextStyle ($properties, $common); } /** * This function creates a paragraph style. * * @see ODTDocument::createParagraphStyle for detailed desciption. */ public function createParagraphStyle ($properties, $common=true) { $this->document->createParagraphStyle ($properties, $common); } /** * This function creates a table style. * * @see ODTDocument::createTableStyle for detailed desciption. */ public function createTableStyle ($properties, $common=true) { $this->document->createTableStyle ($properties, $common); } /** * This function creates a table row style. * * @see ODTDocument::createTableRowStyle for detailed desciption. */ public function createTableRowStyle ($properties, $common=true) { $this->document->createTableRowStyle ($properties, $common); } /** * This function creates a table cell style. * * @see ODTDocument::createTableCellStyle for detailed desciption. */ public function createTableCellStyle ($properties, $common=true) { $this->document->createTableCellStyle ($properties, $common); } /** * This function creates a table column style. * * @see ODTDocument::createTableColumnStyle for detailed desciption. */ public function createTableColumnStyle ($properties, $common=true) { $this->document->createTableColumnStyle ($properties, $common); } public function styleExists ($style_name) { return $this->document->styleExists($style_name); } /** * Add a user field. * (Code has been adopted from the fields plugin) * * @param string $name The name of the field * @param string $value The value of the field * @author Aurelien Bompard * @see ODTDocument::addUserField for detailed desciption. */ public function addUserField($name, $value) { $this->document->addUserField($name, $value); } /** * Insert a user field reference. * (Code has been adopted from the fields plugin) * * @param string $name The name of the field * @author Aurelien Bompard * @see ODTDocument::insertUserField for detailed desciption. */ public function insertUserField($name) { $this->document->insertUserField($name); } protected function buildODTPathes (&$ODTTemplatePath, &$tempDirPath) { global $ID; // Temp dir if (is_dir($this->config->getParam('tmpdir'))) { $tempDirPath = $this->config->getParam('tmpdir'); } $tempDirPath = $tempDirPath."/odt/".str_replace(':','-',$ID); // Eventually determine ODT template file $ODTTemplatePath = NULL; $template = $this->config->getParam ('odt_template'); if (!empty($template)) { $ODTTemplatePath = $this->config->getParam('mediadir').'/'.$this->config->getParam ('tpl_dir')."/".$this->config->getParam ('odt_template'); } } public function addToValue ($value, $add) { return $this->document->addToValue ($value, $add); } public function subFromValue ($value, $sub) { return $this->document->subFromValue ($value, $sub); } public function getHTMLStack () { return $this->document->getHTMLStack (); } public function dumpHTMLStack () { $this->document->dumpHTMLStack (); } public function setOrderedListParams ($setLevel, $align, $paddingLeft=0, $marginLeft=1) { $this->document->setOrderedListParams($setLevel, $align, $paddingLeft, $marginLeft); } public function setUnorderedListParams ($setLevel, $align, $paddingLeft=0, $marginLeft=1) { $this->document->setUnorderedListParams($setLevel, $align, $paddingLeft, $marginLeft); } /** * Insert a bookmark. * * @param string $id ID of the bookmark * @param string $now Insert bookmark immediately? * @see ODTDocument::insertBookmark for detailed desciption. */ public function insertBookmark($id, $now=true) { $this->document->insertBookmark($id, $now); } /** * Automatically generate ODT elements from HTML code. * * @param string $html_code The HTML code to convert * @param array $options Options array (FIXME: documentation needed) * @see ODTUtility::generateODTfromHTMLCode for detailed desciption. */ public function generateODTfromHTMLCode($html_code, $options=null) { // Generate ODT content from Geshi's HTML code $this->document->generateODTfromHTMLCode($html_code, $options); } } //Setup VIM: ex: et ts=4 enc=utf-8 :