1f9f65fc3Swikidesign<?php 2f9f65fc3Swikidesign/** 3f9f65fc3Swikidesign * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 4f9f65fc3Swikidesign * @author Esther Brunner <wikidesign@gmail.com> 5dbdadbd9SGina Haeussge * @author Christopher Smith <chris@jalakai.co.uk> 6dbdadbd9SGina Haeussge * @author Gina Häußge, Michael Klier <dokuwiki@chimeric.de> 7f9f65fc3Swikidesign */ 8f9f65fc3Swikidesign 9f9f65fc3Swikidesign// must be run within Dokuwiki 10f9f65fc3Swikidesignif (!defined('DOKU_INC')) die(); 11f9f65fc3Swikidesign 12f9f65fc3Swikidesignif (!defined('DOKU_LF')) define('DOKU_LF', "\n"); 13f9f65fc3Swikidesignif (!defined('DOKU_TAB')) define('DOKU_TAB', "\t"); 14f9f65fc3Swikidesignif (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC.'lib/plugins/'); 15f9f65fc3Swikidesign 16f9f65fc3Swikidesignclass helper_plugin_include extends DokuWiki_Plugin { // DokuWiki_Helper_Plugin 17f9f65fc3Swikidesign 18b6337848Swikidesign var $pages = array(); // filechain of included pages 19f9f65fc3Swikidesign var $page = array(); // associative array with data about the page to include 20f9f65fc3Swikidesign var $ins = array(); // instructions array 21f9f65fc3Swikidesign var $doc = ''; // the final output XHTML string 22f9f65fc3Swikidesign var $mode = 'section'; // inclusion mode: 'page' or 'section' 23f9f65fc3Swikidesign var $clevel = 0; // current section level 24f9f65fc3Swikidesign var $firstsec = 0; // show first section only 256c836050Swikidesign var $editbtn = 1; // show edit button 266b088758Swikidesign var $footer = 1; // show metaline below page 27990ad87fSwikidesign var $noheader = 0; // omit header 2871ec1101SGina Haeussge var $permalink = 0; // make first headline permalink to included page 29*c44026dcSMichael Hamann var $redirect = 1; // redirect back to original page after an edit 3039af1bf1Swikidesign var $header = array(); // included page / section header 3139af1bf1Swikidesign var $renderer = NULL; // DokuWiki renderer object 32f9f65fc3Swikidesign 33c01ce462SGina Haeussge var $INCLUDE_LIMIT = 12; 34c01ce462SGina Haeussge 35a58d2b0aSwikidesign // private variables 36a58d2b0aSwikidesign var $_offset = NULL; 37a58d2b0aSwikidesign 3852e31fceSwikidesign /** 39656a5d08Swikidesign * Constructor loads some config settings 4052e31fceSwikidesign */ 4152e31fceSwikidesign function helper_plugin_include() { 4252e31fceSwikidesign $this->firstsec = $this->getConf('firstseconly'); 436c836050Swikidesign $this->editbtn = $this->getConf('showeditbtn'); 446b088758Swikidesign $this->footer = $this->getConf('showfooter'); 45*c44026dcSMichael Hamann $this->redirect = $this->getConf('doredirect'); 46cf0272c0Swikidesign $this->noheader = 0; 4771ec1101SGina Haeussge $this->permalink = 0; 48cf0272c0Swikidesign $this->header = array(); 4952e31fceSwikidesign } 5052e31fceSwikidesign 51f9f65fc3Swikidesign function getInfo() { 52f9f65fc3Swikidesign return array( 5371ec1101SGina Haeussge 'author' => 'Gina Häußge, Michael Klier, Esther Brunner', 54dbdadbd9SGina Haeussge 'email' => 'dokuwiki@chimeric.de', 554052f233SGina Haeussge 'date' => @file_get_contents(DOKU_PLUGIN . 'blog/VERSION'), 56f9f65fc3Swikidesign 'name' => 'Include Plugin (helper class)', 57f9f65fc3Swikidesign 'desc' => 'Functions to include another page in a wiki page', 581f7a99c4SMichael Klier 'url' => 'http://wiki.splitbrain.org/plugin:include', 59f9f65fc3Swikidesign ); 60f9f65fc3Swikidesign } 61f9f65fc3Swikidesign 62f9f65fc3Swikidesign function getMethods() { 63f9f65fc3Swikidesign $result = array(); 64f9f65fc3Swikidesign $result[] = array( 65f9f65fc3Swikidesign 'name' => 'setPage', 66f9f65fc3Swikidesign 'desc' => 'sets the page to include', 67f9f65fc3Swikidesign 'params' => array("page attributes, 'id' required, 'section' for filtering" => 'array'), 68f9f65fc3Swikidesign 'return' => array('success' => 'boolean'), 69f9f65fc3Swikidesign ); 70f9f65fc3Swikidesign $result[] = array( 71f9f65fc3Swikidesign 'name' => 'setMode', 72f9f65fc3Swikidesign 'desc' => 'sets inclusion mode: should indention be merged?', 73f9f65fc3Swikidesign 'params' => array("'page' (original) or 'section' (merged indention)" => 'string'), 74f9f65fc3Swikidesign ); 75f9f65fc3Swikidesign $result[] = array( 76f9f65fc3Swikidesign 'name' => 'setLevel', 77f9f65fc3Swikidesign 'desc' => 'sets the indention for the current section level', 78f9f65fc3Swikidesign 'params' => array('level: 0 to 5' => 'integer'), 79f9f65fc3Swikidesign 'return' => array('success' => 'boolean'), 80f9f65fc3Swikidesign ); 81f9f65fc3Swikidesign $result[] = array( 82656a5d08Swikidesign 'name' => 'setFlags', 836b088758Swikidesign 'desc' => 'overrides standard values for showfooter and firstseconly settings', 84656a5d08Swikidesign 'params' => array('flags' => 'array'), 85656a5d08Swikidesign ); 86656a5d08Swikidesign $result[] = array( 87b6337848Swikidesign 'name' => 'renderXHTML', 88b6337848Swikidesign 'desc' => 'renders the XHTML output of the included page', 89f9f65fc3Swikidesign 'params' => array('DokuWiki renderer' => 'object'), 90b6337848Swikidesign 'return' => array('XHTML' => 'string'), 91f9f65fc3Swikidesign ); 92f9f65fc3Swikidesign return $result; 93f9f65fc3Swikidesign } 94f9f65fc3Swikidesign 95f9f65fc3Swikidesign /** 96f9f65fc3Swikidesign * Sets the page to include if it is not already included (prevent recursion) 97990ad87fSwikidesign * and the current user is allowed to read it 98f9f65fc3Swikidesign */ 99f9f65fc3Swikidesign function setPage($page) { 100f9f65fc3Swikidesign global $ID; 101f9f65fc3Swikidesign 102b6337848Swikidesign $id = $page['id']; 103b6337848Swikidesign $fullid = $id.'#'.$page['section']; 104f9f65fc3Swikidesign 105b6337848Swikidesign if (!$id) return false; // no page id given 106b6337848Swikidesign if ($id == $ID) return false; // page can't include itself 107f9f65fc3Swikidesign 108b6337848Swikidesign // prevent include recursion 109c01ce462SGina Haeussge if ($this->_in_filechain($id,$page['section']) || (count($this->pages) >= $this->INCLUDE_LIMIT)) return false; 110b6337848Swikidesign 111990ad87fSwikidesign // we need to make sure 'perm', 'file' and 'exists' are set 112990ad87fSwikidesign if (!isset($page['perm'])) $page['perm'] = auth_quickaclcheck($page['id']); 113990ad87fSwikidesign if (!isset($page['file'])) $page['file'] = wikiFN($page['id']); 114990ad87fSwikidesign if (!isset($page['exists'])) $page['exists'] = @file_exists($page['file']); 115990ad87fSwikidesign 116990ad87fSwikidesign // check permission 117f83ac5f7Swikidesign if ($page['perm'] < AUTH_READ) return false; 118990ad87fSwikidesign 119b6337848Swikidesign // add the page to the filechain 120c01ce462SGina Haeussge $this->page = $page; 121f9f65fc3Swikidesign return true; 122f9f65fc3Swikidesign } 123f9f65fc3Swikidesign 124c01ce462SGina Haeussge function _push_page($id,$section) { 125c01ce462SGina Haeussge global $ID; 126c01ce462SGina Haeussge if (empty($this->pages)) array_push($this->pages, $ID.'#'); 127c01ce462SGina Haeussge array_push($this->pages, $id.'#'.$section); 128c01ce462SGina Haeussge } 129c01ce462SGina Haeussge 130c01ce462SGina Haeussge function _pop_page() { 131c01ce462SGina Haeussge $page = array_pop($this->pages); 132c01ce462SGina Haeussge if (count($this->pages=1)) $this->pages = array(); 133c01ce462SGina Haeussge 134c01ce462SGina Haeussge return $page; 135c01ce462SGina Haeussge } 136c01ce462SGina Haeussge 137c01ce462SGina Haeussge function _in_filechain($id,$section) { 138c01ce462SGina Haeussge $pattern = $section ? "/^($id#$section|$id#)$/" : "/^$id#/"; 139c01ce462SGina Haeussge $match = preg_grep($pattern, $this->pages); 140c01ce462SGina Haeussge 141c01ce462SGina Haeussge return (!empty($match)); 142c01ce462SGina Haeussge } 143c01ce462SGina Haeussge 144f9f65fc3Swikidesign /** 145a3a7e530Swikidesign * Sets the inclusion mode: 'page' or 'section' 146f9f65fc3Swikidesign */ 147f9f65fc3Swikidesign function setMode($mode) { 148f9f65fc3Swikidesign $this->mode = $mode; 149f9f65fc3Swikidesign } 150f9f65fc3Swikidesign 151f9f65fc3Swikidesign /** 152f9f65fc3Swikidesign * Sets the right indention for a given section level 153f9f65fc3Swikidesign */ 154f9f65fc3Swikidesign function setLevel($level) { 155f9f65fc3Swikidesign if ((is_numeric($level)) && ($level >= 0) && ($level <= 5)) { 156f9f65fc3Swikidesign $this->clevel = $level; 157f9f65fc3Swikidesign return true; 158f9f65fc3Swikidesign } 159f9f65fc3Swikidesign return false; 160f9f65fc3Swikidesign } 161f9f65fc3Swikidesign 162f9f65fc3Swikidesign /** 1636b088758Swikidesign * Overrides standard values for showfooter and firstseconly settings 164656a5d08Swikidesign */ 165656a5d08Swikidesign function setFlags($flags) { 166656a5d08Swikidesign foreach ($flags as $flag) { 167656a5d08Swikidesign switch ($flag) { 1686b088758Swikidesign case 'footer': 1696b088758Swikidesign $this->footer = 1; 170656a5d08Swikidesign break; 1716b088758Swikidesign case 'nofooter': 1726b088758Swikidesign $this->footer = 0; 173656a5d08Swikidesign break; 174656a5d08Swikidesign case 'firstseconly': 17543dcb6deSwikidesign case 'firstsectiononly': 176656a5d08Swikidesign $this->firstsec = 1; 177656a5d08Swikidesign break; 178656a5d08Swikidesign case 'fullpage': 179656a5d08Swikidesign $this->firstsec = 0; 180656a5d08Swikidesign break; 181990ad87fSwikidesign case 'noheader': 182990ad87fSwikidesign $this->noheader = 1; 183990ad87fSwikidesign break; 18443dcb6deSwikidesign case 'editbtn': 185a3a7e530Swikidesign case 'editbutton': 1866c836050Swikidesign $this->editbtn = 1; 1876c836050Swikidesign break; 18843dcb6deSwikidesign case 'noeditbtn': 189a3a7e530Swikidesign case 'noeditbutton': 1906c836050Swikidesign $this->editbtn = 0; 1916c836050Swikidesign break; 19271ec1101SGina Haeussge case 'permalink': 19371ec1101SGina Haeussge $this->permalink = 1; 19471ec1101SGina Haeussge break; 19571ec1101SGina Haeussge case 'nopermalink': 19671ec1101SGina Haeussge $this->permalink = 0; 19771ec1101SGina Haeussge break; 198*c44026dcSMichael Hamann case 'redirect': 199*c44026dcSMichael Hamann $this->redirect = 1; 200*c44026dcSMichael Hamann break; 201*c44026dcSMichael Hamann case 'noredirect': 202*c44026dcSMichael Hamann $this->redirect = 0; 203*c44026dcSMichael Hamann break; 204656a5d08Swikidesign } 205656a5d08Swikidesign } 206656a5d08Swikidesign } 207656a5d08Swikidesign 208656a5d08Swikidesign /** 209f9f65fc3Swikidesign * Builds the XHTML to embed the page to include 210f9f65fc3Swikidesign */ 211c01ce462SGina Haeussge function renderXHTML(&$renderer, &$info) { 21251b9ed81Swikidesign global $ID; 21351b9ed81Swikidesign 214b6337848Swikidesign if (!$this->page['id']) return ''; // page must be set first 21558de0a6fSwikidesign if (!$this->page['exists'] && ($this->page['perm'] < AUTH_CREATE)) return ''; 216f9f65fc3Swikidesign 217c01ce462SGina Haeussge $this->_push_page($this->page['id'],$this->page['section']); 218c01ce462SGina Haeussge 21952e31fceSwikidesign // prepare variables 220c01ce462SGina Haeussge $rdoc = $renderer->doc; 221c01ce462SGina Haeussge $doc = ''; 22239af1bf1Swikidesign $this->renderer =& $renderer; 223f9f65fc3Swikidesign 224c01ce462SGina Haeussge $page = $this->page; 225c01ce462SGina Haeussge $clevel = $this->clevel; 226c01ce462SGina Haeussge $mode = $this->mode; 227c01ce462SGina Haeussge 2288c434f1aSGina Haeussge // exchange page ID for included one 2298c434f1aSGina Haeussge $backupID = $ID; // store the current ID 2308c434f1aSGina Haeussge $ID = $this->page['id']; // change ID to the included page 2318c434f1aSGina Haeussge 232f9f65fc3Swikidesign // get instructions and render them on the fly 233f9f65fc3Swikidesign $this->ins = p_cached_instructions($this->page['file']); 234f9f65fc3Swikidesign 235f9f65fc3Swikidesign // show only a given section? 236656a5d08Swikidesign if ($this->page['section'] && $this->page['exists']) $this->_getSection(); 237f9f65fc3Swikidesign 238f9f65fc3Swikidesign // convert relative links 23939af1bf1Swikidesign $this->_convertInstructions(); 240f9f65fc3Swikidesign 241c01ce462SGina Haeussge $xhtml = p_render('xhtml', $this->ins, $info); 242c01ce462SGina Haeussge $ID = $backupID; // restore ID 243c01ce462SGina Haeussge 244c01ce462SGina Haeussge $this->mode = $mode; 245c01ce462SGina Haeussge $this->clevel = $clevel; 246c01ce462SGina Haeussge $this->page = $page; 247c01ce462SGina Haeussge 248f9f65fc3Swikidesign // render the included page 249990ad87fSwikidesign $content = '<div class="entry-content">'.DOKU_LF. 250c01ce462SGina Haeussge $this->_cleanXHTML($xhtml).DOKU_LF. 251c01ce462SGina Haeussge '</div><!-- .entry-content -->'.DOKU_LF; 2528c434f1aSGina Haeussge 2538c434f1aSGina Haeussge // restore ID 2548c434f1aSGina Haeussge $ID = $backupID; 255f9f65fc3Swikidesign 256f9f65fc3Swikidesign // embed the included page 257e62bb8f0Swikidesign $class = ($this->page['draft'] ? 'include draft' : 'include'); 258c01ce462SGina Haeussge 259c01ce462SGina Haeussge $doc .= DOKU_LF.'<!-- including '.$this->page['id'].' // '.$this->page['file'].' -->'.DOKU_LF; 260c01ce462SGina Haeussge $doc .= '<div class="'.$class.' hentry"'.$this->_showTagLogos().'>'.DOKU_LF; 26139af1bf1Swikidesign if (!$this->header && $this->clevel && ($this->mode == 'section')) 262c01ce462SGina Haeussge $doc .= '<div class="level'.$this->clevel.'">'.DOKU_LF; 263c01ce462SGina Haeussge 2648d99695dSwikidesign if ((@file_exists(DOKU_PLUGIN.'editsections/action.php')) 2658d99695dSwikidesign && (!plugin_isdisabled('editsections'))) { // for Edit Section Reorganizer Plugin 266c01ce462SGina Haeussge $doc .= $this->_editButton().$content; 2676cad866dSwikidesign } else { 268c01ce462SGina Haeussge $doc .= $content.$this->_editButton(); 2696cad866dSwikidesign } 270656a5d08Swikidesign 271ec00fca6Swikidesign // output meta line (if wanted) and remove page from filechain 272c01ce462SGina Haeussge $doc .= $this->_footer($this->page); 273ec00fca6Swikidesign 27439af1bf1Swikidesign if (!$this->header && $this->clevel && ($this->mode == 'section')) 275c01ce462SGina Haeussge $doc .= '</div>'.DOKU_LF; // class="level?" 276c01ce462SGina Haeussge $doc .= '</div>'.DOKU_LF; // class="include hentry" 277c01ce462SGina Haeussge $doc .= DOKU_LF.'<!-- /including '.$this->page['id'].' -->'.DOKU_LF; 278f9f65fc3Swikidesign 279ec00fca6Swikidesign // reset defaults 280656a5d08Swikidesign $this->helper_plugin_include(); 281c01ce462SGina Haeussge $this->_pop_page(); 282f9f65fc3Swikidesign 283ec00fca6Swikidesign // return XHTML 284c01ce462SGina Haeussge $renderer->doc = $rdoc.$doc; 285c01ce462SGina Haeussge return $doc; 286f9f65fc3Swikidesign } 287f9f65fc3Swikidesign 288f9f65fc3Swikidesign /* ---------- Private Methods ---------- */ 289f9f65fc3Swikidesign 290f9f65fc3Swikidesign /** 291f9f65fc3Swikidesign * Get a section including its subsections 292f9f65fc3Swikidesign */ 293f9f65fc3Swikidesign function _getSection() { 294f9f65fc3Swikidesign foreach ($this->ins as $ins) { 295f9f65fc3Swikidesign if ($ins[0] == 'header') { 296f9f65fc3Swikidesign 297f9f65fc3Swikidesign // found the right header 298f9f65fc3Swikidesign if (cleanID($ins[1][0]) == $this->page['section']) { 299f9f65fc3Swikidesign $level = $ins[1][1]; 300f9f65fc3Swikidesign $i[] = $ins; 301f9f65fc3Swikidesign 302f9f65fc3Swikidesign // next header of the same or higher level -> exit 303f9f65fc3Swikidesign } elseif ($ins[1][1] <= $level) { 304f9f65fc3Swikidesign $this->ins = $i; 305f9f65fc3Swikidesign return true; 306f9f65fc3Swikidesign } elseif (isset($level)) { 307f9f65fc3Swikidesign $i[] = $ins; 308f9f65fc3Swikidesign } 309f9f65fc3Swikidesign 310f9f65fc3Swikidesign // add instructions from our section 311f9f65fc3Swikidesign } elseif (isset($level)) { 312f9f65fc3Swikidesign $i[] = $ins; 313f9f65fc3Swikidesign } 314f9f65fc3Swikidesign } 315f9f65fc3Swikidesign $this->ins = $i; 316f9f65fc3Swikidesign return true; 317f9f65fc3Swikidesign } 318f9f65fc3Swikidesign 319f9f65fc3Swikidesign /** 320f9f65fc3Swikidesign * Corrects relative internal links and media and 321f9f65fc3Swikidesign * converts headers of included pages to subheaders of the current page 322f9f65fc3Swikidesign */ 32339af1bf1Swikidesign function _convertInstructions() { 32451b9ed81Swikidesign global $ID; 32551b9ed81Swikidesign 32658de0a6fSwikidesign if (!$this->page['exists']) return false; 32758de0a6fSwikidesign 328f9f65fc3Swikidesign // check if included page is in same namespace 3299a79957fSwikidesign $ns = getNS($this->page['id']); 33051b9ed81Swikidesign $convert = (getNS($ID) == $ns ? false : true); 331f9f65fc3Swikidesign 332f9f65fc3Swikidesign $n = count($this->ins); 333f9f65fc3Swikidesign for ($i = 0; $i < $n; $i++) { 334a58d2b0aSwikidesign $current = $this->ins[$i][0]; 335f9f65fc3Swikidesign 336f9f65fc3Swikidesign // convert internal links and media from relative to absolute 337a58d2b0aSwikidesign if ($convert && (substr($current, 0, 8) == 'internal')) { 3389a79957fSwikidesign $this->ins[$i][1][0] = $this->_convertInternalLink($this->ins[$i][1][0], $ns); 339a58d2b0aSwikidesign 340a58d2b0aSwikidesign // set header level to current section level + header level 341a58d2b0aSwikidesign } elseif ($current == 'header') { 3429a79957fSwikidesign $this->_convertHeader($i); 343a58d2b0aSwikidesign 344a58d2b0aSwikidesign // the same for sections 3459a79957fSwikidesign } elseif (($current == 'section_open') && ($this->mode == 'section')) { 346a58d2b0aSwikidesign $this->ins[$i][1][0] = $this->_convertSectionLevel($this->ins[$i][1][0]); 347a58d2b0aSwikidesign 348a58d2b0aSwikidesign // show only the first section? 349a58d2b0aSwikidesign } elseif ($this->firstsec && ($current == 'section_close') 350a58d2b0aSwikidesign && ($this->ins[$i-1][0] != 'section_open')) { 351a58d2b0aSwikidesign $this->_readMore($i); 352a58d2b0aSwikidesign return true; 353a58d2b0aSwikidesign } 354a58d2b0aSwikidesign } 355a58d2b0aSwikidesign $this->_finishConvert(); 356a58d2b0aSwikidesign return true; 357a58d2b0aSwikidesign } 358a58d2b0aSwikidesign 359a58d2b0aSwikidesign /** 360a58d2b0aSwikidesign * Convert relative internal links and media 361a58d2b0aSwikidesign * 362a58d2b0aSwikidesign * @param integer $i: counter for current instruction 363a58d2b0aSwikidesign * @param string $ns: namespace of included page 364a58d2b0aSwikidesign * @return string $link: converted, now absolute link 365a58d2b0aSwikidesign */ 3669a79957fSwikidesign function _convertInternalLink($link, $ns) { 367f9f65fc3Swikidesign 368f9f65fc3Swikidesign // relative subnamespace 3699a79957fSwikidesign if ($link{0} == '.') { 3709a79957fSwikidesign if ($link{1} == '.') return getNS($ns).':'.substr($link, 2); // parent namespace 3719a79957fSwikidesign else return $ns.':'.substr($link, 1); // current namespace 372f9f65fc3Swikidesign 373f9f65fc3Swikidesign // relative link 3749a79957fSwikidesign } elseif (strpos($link, ':') === false) { 3759a79957fSwikidesign return $ns.':'.$link; 3769a79957fSwikidesign 3779a79957fSwikidesign // absolute link - don't change 3789a79957fSwikidesign } else { 3799a79957fSwikidesign return $link; 380a58d2b0aSwikidesign } 381f9f65fc3Swikidesign } 382f9f65fc3Swikidesign 383a58d2b0aSwikidesign /** 384a58d2b0aSwikidesign * Convert header level and add header to TOC 385a58d2b0aSwikidesign * 386a58d2b0aSwikidesign * @param integer $i: counter for current instruction 387a58d2b0aSwikidesign * @return boolean true 388a58d2b0aSwikidesign */ 3899a79957fSwikidesign function _convertHeader($i) { 390cf0272c0Swikidesign global $conf; 391cf0272c0Swikidesign 392f9f65fc3Swikidesign $text = $this->ins[$i][1][0]; 39339af1bf1Swikidesign $hid = $this->renderer->_headerToLink($text, 'true'); 394b448b725Swikidesign if (empty($this->header)) { 395a58d2b0aSwikidesign $this->_offset = $this->clevel - $this->ins[$i][1][1] + 1; 396cf0272c0Swikidesign $level = $this->_convertSectionLevel(1); 397cf0272c0Swikidesign $this->header = array('hid' => $hid, 'title' => hsc($text), 'level' => $level); 398990ad87fSwikidesign if ($this->noheader) { 39939af1bf1Swikidesign unset($this->ins[$i]); 400990ad87fSwikidesign return true; 40171ec1101SGina Haeussge } else if ($this->permalink){ 4024eb6b7abSGina Haeussge $this->ins[$i] = $this->_permalinkHeader($text, $level, $this->ins[$i][1][2]); 403990ad87fSwikidesign } 404656a5d08Swikidesign } else { 405a58d2b0aSwikidesign $level = $this->_convertSectionLevel($this->ins[$i][1][1]); 40639af1bf1Swikidesign } 40771ec1101SGina Haeussge if ($this->mode == 'section') { 4084eb6b7abSGina Haeussge if (is_array($this->ins[$i][1][1])) { // permalink header 40971ec1101SGina Haeussge $this->ins[$i][1][1][1] = $level; 4104eb6b7abSGina Haeussge } else { // normal header 41171ec1101SGina Haeussge $this->ins[$i][1][1] = $level; 41271ec1101SGina Haeussge } 41371ec1101SGina Haeussge } 414990ad87fSwikidesign 415a58d2b0aSwikidesign // add TOC item 416656a5d08Swikidesign if (($level >= $conf['toptoclevel']) && ($level <= $conf['maxtoclevel'])) { 417656a5d08Swikidesign $this->renderer->toc[] = array( 418656a5d08Swikidesign 'hid' => $hid, 419656a5d08Swikidesign 'title' => $text, 420656a5d08Swikidesign 'type' => 'ul', 421656a5d08Swikidesign 'level' => $level - $conf['toptoclevel'] + 1 422656a5d08Swikidesign ); 423f9f65fc3Swikidesign } 424f9f65fc3Swikidesign return true; 425a58d2b0aSwikidesign } 426a58d2b0aSwikidesign 427a58d2b0aSwikidesign /** 42871ec1101SGina Haeussge * Create instruction item for a permalink header 42971ec1101SGina Haeussge * 43071ec1101SGina Haeussge * @param string $text: Headline text 43171ec1101SGina Haeussge * @param integer $level: Headline level 43271ec1101SGina Haeussge * @param integer $pos: I wish I knew what this is for... 43371ec1101SGina Haeussge * 43471ec1101SGina Haeussge * @author Gina Haeussge <osd@foosel.net> 43571ec1101SGina Haeussge */ 43671ec1101SGina Haeussge function _permalinkHeader($text, $level, $pos) { 43771ec1101SGina Haeussge $newIns = array( 43871ec1101SGina Haeussge 'plugin', 43971ec1101SGina Haeussge array( 44071ec1101SGina Haeussge 'include_header', 44171ec1101SGina Haeussge array( 44271ec1101SGina Haeussge $text, 4434eb6b7abSGina Haeussge $level 44471ec1101SGina Haeussge ), 44571ec1101SGina Haeussge ), 44671ec1101SGina Haeussge $pos 44771ec1101SGina Haeussge ); 44871ec1101SGina Haeussge 44971ec1101SGina Haeussge return $newIns; 45071ec1101SGina Haeussge } 45171ec1101SGina Haeussge 45271ec1101SGina Haeussge /** 453a58d2b0aSwikidesign * Convert the level of headers and sections 454a58d2b0aSwikidesign * 455a58d2b0aSwikidesign * @param integer $in: current level 456a58d2b0aSwikidesign * @return integer $out: converted level 457a58d2b0aSwikidesign */ 458a58d2b0aSwikidesign function _convertSectionLevel($in) { 459a58d2b0aSwikidesign $out = $in + $this->_offset; 460cf0272c0Swikidesign if ($out >= 5) return 5; 461cf0272c0Swikidesign if ($out <= $this->clevel + 1) return $this->clevel + 1; 462a58d2b0aSwikidesign return $out; 463a58d2b0aSwikidesign } 464a58d2b0aSwikidesign 465a58d2b0aSwikidesign /** 466a58d2b0aSwikidesign * Adds a read more... link at the bottom of the first section 467a58d2b0aSwikidesign * 468a58d2b0aSwikidesign * @param integer $i: counter for current instruction 469a58d2b0aSwikidesign * @return boolean true 470a58d2b0aSwikidesign */ 471a58d2b0aSwikidesign function _readMore($i) { 472a58d2b0aSwikidesign $more = ((is_array($this->ins[$i+1])) && ($this->ins[$i+1][0] != 'document_end')); 473a58d2b0aSwikidesign 474a58d2b0aSwikidesign if ($this->ins[0][0] == 'document_start') $this->ins = array_slice($this->ins, 1, $i); 475a58d2b0aSwikidesign else $this->ins = array_slice($this->ins, 0, $i); 476a58d2b0aSwikidesign 477a58d2b0aSwikidesign if ($more) { 478a58d2b0aSwikidesign array_unshift($this->ins, array('document_start', array(), 0)); 479a58d2b0aSwikidesign $last = array_pop($this->ins); 480a58d2b0aSwikidesign $this->ins[] = array('p_open', array(), $last[2]); 481a58d2b0aSwikidesign $this->ins[] = array('internallink',array($this->page['id'], $this->getLang('readmore')),$last[2]); 482a58d2b0aSwikidesign $this->ins[] = array('p_close', array(), $last[2]); 483a58d2b0aSwikidesign $this->ins[] = $last; 484a58d2b0aSwikidesign $this->ins[] = array('document_end', array(), $last[2]); 485f9f65fc3Swikidesign } else { 486a58d2b0aSwikidesign $this->_finishConvert(); 487a58d2b0aSwikidesign } 488f9f65fc3Swikidesign return true; 489f9f65fc3Swikidesign } 490a58d2b0aSwikidesign 491a58d2b0aSwikidesign /** 492a58d2b0aSwikidesign * Adds 'document_start' and 'document_end' instructions if not already there 493a58d2b0aSwikidesign */ 494a58d2b0aSwikidesign function _finishConvert() { 495b088012cSwikidesign if ($this->ins[0][0] != 'document_start') 49678f60e2aSwikidesign array_unshift($this->ins, array('document_start', array(), 0)); 497b088012cSwikidesign $c = count($this->ins) - 1; 498b088012cSwikidesign if ($this->ins[$c][0] != 'document_end') 49978f60e2aSwikidesign $this->ins[] = array('document_end', array(), 0); 50078f60e2aSwikidesign } 501f9f65fc3Swikidesign 502f9f65fc3Swikidesign /** 503f9f65fc3Swikidesign * Remove TOC, section edit buttons and tags 504f9f65fc3Swikidesign */ 505f9f65fc3Swikidesign function _cleanXHTML($xhtml) { 506f9f65fc3Swikidesign $replace = array( 507f9f65fc3Swikidesign '!<div class="toc">.*?(</div>\n</div>)!s' => '', // remove toc 508f9f65fc3Swikidesign '#<!-- SECTION "(.*?)" \[(\d+-\d*)\] -->#e' => '', // remove section edit buttons 509f9f65fc3Swikidesign '!<div class="tags">.*?(</div>)!s' => '', // remove category tags 510f9f65fc3Swikidesign ); 511b088012cSwikidesign if ($this->clevel) 512b088012cSwikidesign $replace['#<div class="footnotes">#s'] = '<div class="footnotes level'.$this->clevel.'">'; 513f9f65fc3Swikidesign $xhtml = preg_replace(array_keys($replace), array_values($replace), $xhtml); 514f9f65fc3Swikidesign return $xhtml; 515f9f65fc3Swikidesign } 516f9f65fc3Swikidesign 517f9f65fc3Swikidesign /** 518f9f65fc3Swikidesign * Optionally display logo for the first tag found in the included page 519f9f65fc3Swikidesign */ 520f9f65fc3Swikidesign function _showTagLogos() { 521fc5d061eSwikidesign if ((!$this->getConf('showtaglogos')) 522fc5d061eSwikidesign || (plugin_isdisabled('tag')) 523fc5d061eSwikidesign || (!$taghelper =& plugin_load('helper', 'tag'))) 524fc5d061eSwikidesign return ''; 525f9f65fc3Swikidesign 526fc5d061eSwikidesign $subject = p_get_metadata($this->page['id'], 'subject'); 527fc5d061eSwikidesign if (is_array($subject)) $tag = $subject[0]; 528fc5d061eSwikidesign else list($tag, $rest) = explode(' ', $subject, 2); 529fc5d061eSwikidesign $title = str_replace('_', ' ', noNS($tag)); 530fc5d061eSwikidesign resolve_pageid($taghelper->namespace, $tag, $exists); // resolve shortcuts 531fc5d061eSwikidesign 532f9f65fc3Swikidesign $logosrc = mediaFN($logoID); 533f9f65fc3Swikidesign $types = array('.png', '.jpg', '.gif'); // auto-detect filetype 534f9f65fc3Swikidesign foreach ($types as $type) { 535f9f65fc3Swikidesign if (!@file_exists($logosrc.$type)) continue; 536fc5d061eSwikidesign $logoID = $tag.$type; 537f9f65fc3Swikidesign $logosrc .= $type; 538f9f65fc3Swikidesign list($w, $h, $t, $a) = getimagesize($logosrc); 539f9f65fc3Swikidesign return ' style="min-height: '.$h.'px">'. 540fc5d061eSwikidesign '<img class="mediaright" src="'.ml($logoID).'" alt="'.$title.'"/'; 541f9f65fc3Swikidesign } 542f9f65fc3Swikidesign return ''; 543f9f65fc3Swikidesign } 544f9f65fc3Swikidesign 545f9f65fc3Swikidesign /** 546f9f65fc3Swikidesign * Display an edit button for the included page 547f9f65fc3Swikidesign */ 548f9f65fc3Swikidesign function _editButton() { 549*c44026dcSMichael Hamann global $ID; 550990ad87fSwikidesign if ($this->page['exists']) { 551f9f65fc3Swikidesign if (($this->page['perm'] >= AUTH_EDIT) && (is_writable($this->page['file']))) 552f9f65fc3Swikidesign $action = 'edit'; 553f9f65fc3Swikidesign else return ''; 554f9f65fc3Swikidesign } elseif ($this->page['perm'] >= AUTH_CREATE) { 555f9f65fc3Swikidesign $action = 'create'; 556f9f65fc3Swikidesign } 5576c836050Swikidesign if ($this->editbtn) { 558*c44026dcSMichael Hamann $params = array('do' => 'edit'); 559*c44026dcSMichael Hamann if ($this->redirect) 560*c44026dcSMichael Hamann $params['redirect_id'] = $ID; 561f9f65fc3Swikidesign return '<div class="secedit">'.DOKU_LF.DOKU_TAB. 562*c44026dcSMichael Hamann html_btn($action, $this->page['id'], '', $params, 'post').DOKU_LF. 563f9f65fc3Swikidesign '</div>'.DOKU_LF; 5643c01153cSwikidesign } else { 5653c01153cSwikidesign return ''; 5663c01153cSwikidesign } 567f9f65fc3Swikidesign } 568f9f65fc3Swikidesign 569f9f65fc3Swikidesign /** 570f9f65fc3Swikidesign * Returns the meta line below the included page 571f9f65fc3Swikidesign */ 5726b088758Swikidesign function _footer($page) { 573817828faSwikidesign global $conf, $ID; 574817828faSwikidesign 5756b088758Swikidesign if (!$this->footer) return ''; // '<div class="inclmeta"> </div>'.DOKU_LF; 576f9f65fc3Swikidesign 577b6337848Swikidesign $id = $page['id']; 578f9f65fc3Swikidesign $meta = p_get_metadata($id); 579f9f65fc3Swikidesign $ret = array(); 580f9f65fc3Swikidesign 581f9f65fc3Swikidesign // permalink 582f9f65fc3Swikidesign if ($this->getConf('showlink')) { 583b6337848Swikidesign $title = ($page['title'] ? $page['title'] : $meta['title']); 584f9f65fc3Swikidesign if (!$title) $title = str_replace('_', ' ', noNS($id)); 585656a5d08Swikidesign $class = ($page['exists'] ? 'wikilink1' : 'wikilink2'); 58639af1bf1Swikidesign $link = array( 58739af1bf1Swikidesign 'url' => wl($id), 58839af1bf1Swikidesign 'title' => $id, 58939af1bf1Swikidesign 'name' => hsc($title), 59039af1bf1Swikidesign 'target' => $conf['target']['wiki'], 591656a5d08Swikidesign 'class' => $class.' permalink', 59239af1bf1Swikidesign 'more' => 'rel="bookmark"', 59339af1bf1Swikidesign ); 59439af1bf1Swikidesign $ret[] = $this->renderer->_formatLink($link); 595f9f65fc3Swikidesign } 596f9f65fc3Swikidesign 597f9f65fc3Swikidesign // date 598f9f65fc3Swikidesign if ($this->getConf('showdate')) { 599b6337848Swikidesign $date = ($page['date'] ? $page['date'] : $meta['date']['created']); 60039af1bf1Swikidesign if ($date) 601ee335396SMichael Klier $ret[] = '<abbr class="published" title="'.strftime('%Y-%m-%dT%H:%M:%SZ', $date).'">'. 602ee335396SMichael Klier strftime($conf['dformat'], $date). 60339af1bf1Swikidesign '</abbr>'; 604f9f65fc3Swikidesign } 605f9f65fc3Swikidesign 606f9f65fc3Swikidesign // author 607f9f65fc3Swikidesign if ($this->getConf('showuser')) { 608b6337848Swikidesign $author = ($page['user'] ? $page['user'] : $meta['creator']); 609f9f65fc3Swikidesign if ($author) { 610f9f65fc3Swikidesign $userpage = cleanID($this->getConf('usernamespace').':'.$author); 61151b9ed81Swikidesign resolve_pageid(getNS($ID), $userpage, $exists); 61239af1bf1Swikidesign $class = ($exists ? 'wikilink1' : 'wikilink2'); 61339af1bf1Swikidesign $link = array( 61439af1bf1Swikidesign 'url' => wl($userpage), 61539af1bf1Swikidesign 'title' => $userpage, 61639af1bf1Swikidesign 'name' => hsc($author), 61739af1bf1Swikidesign 'target' => $conf['target']['wiki'], 61839af1bf1Swikidesign 'class' => $class.' url fn', 61939af1bf1Swikidesign 'pre' => '<span class="vcard author">', 62039af1bf1Swikidesign 'suf' => '</span>', 62139af1bf1Swikidesign ); 62239af1bf1Swikidesign $ret[] = $this->renderer->_formatLink($link); 623f9f65fc3Swikidesign } 624f9f65fc3Swikidesign } 625f9f65fc3Swikidesign 626f9f65fc3Swikidesign // comments - let Discussion Plugin do the work for us 627b6337848Swikidesign if (!$page['section'] && $this->getConf('showcomments') 628e4624397Swikidesign && (!plugin_isdisabled('discussion')) 629e4624397Swikidesign && ($discussion =& plugin_load('helper', 'discussion'))) { 630e4624397Swikidesign $disc = $discussion->td($id); 63139af1bf1Swikidesign if ($disc) $ret[] = '<span class="comment">'.$disc.'</span>'; 632f9f65fc3Swikidesign } 633f9f65fc3Swikidesign 634564e71f6Sraymond.scholz // linkbacks - let Linkback Plugin do the work for us 635564e71f6Sraymond.scholz if (!$page['section'] && $this->getConf('showlinkbacks') 636564e71f6Sraymond.scholz && (!plugin_isdisabled('linkback')) 637564e71f6Sraymond.scholz && ($linkback =& plugin_load('helper', 'linkback'))) { 638564e71f6Sraymond.scholz $link = $linkback->td($id); 639564e71f6Sraymond.scholz if ($link) $ret[] = '<span class="linkback">'.$link.'</span>'; 640564e71f6Sraymond.scholz } 641564e71f6Sraymond.scholz 642ec00fca6Swikidesign $ret = implode(DOKU_LF.DOKU_TAB.'· ', $ret); 643f9f65fc3Swikidesign 644fc5d061eSwikidesign // tags - let Tag Plugin do the work for us 645fc5d061eSwikidesign if (!$page['section'] && $this->getConf('showtags') 646fc5d061eSwikidesign && (!plugin_isdisabled('tag')) 647fc5d061eSwikidesign && ($tag =& plugin_load('helper', 'tag'))) { 648fc5d061eSwikidesign $page['tags'] = '<div class="tags"><span>'.DOKU_LF. 649fc5d061eSwikidesign DOKU_TAB.$tag->td($id).DOKU_LF. 650fc5d061eSwikidesign DOKU_TAB.'</span></div>'.DOKU_LF; 651fc5d061eSwikidesign $ret = $page['tags'].DOKU_TAB.$ret; 652f9f65fc3Swikidesign } 653f9f65fc3Swikidesign 654f9f65fc3Swikidesign if (!$ret) $ret = ' '; 655ec00fca6Swikidesign $class = 'inclmeta'; 656ec00fca6Swikidesign if ($this->header && $this->clevel && ($this->mode == 'section')) 657ec00fca6Swikidesign $class .= ' level'.$this->clevel; 658ec00fca6Swikidesign return '<div class="'.$class.'">'.DOKU_LF.DOKU_TAB.$ret.DOKU_LF.'</div>'.DOKU_LF; 659f9f65fc3Swikidesign } 660f9f65fc3Swikidesign 6611f7a99c4SMichael Klier /** 6621f7a99c4SMichael Klier * Builds the ODT to embed the page to include 6631f7a99c4SMichael Klier */ 6641f7a99c4SMichael Klier function renderODT(&$renderer) { 6651f7a99c4SMichael Klier global $ID; 6661f7a99c4SMichael Klier 6671f7a99c4SMichael Klier if (!$this->page['id']) return ''; // page must be set first 6681f7a99c4SMichael Klier if (!$this->page['exists'] && ($this->page['perm'] < AUTH_CREATE)) return ''; 6691f7a99c4SMichael Klier 6701f7a99c4SMichael Klier // prepare variable 6711f7a99c4SMichael Klier $this->renderer =& $renderer; 6721f7a99c4SMichael Klier 6731f7a99c4SMichael Klier // get instructions and render them on the fly 6741f7a99c4SMichael Klier $this->ins = p_cached_instructions($this->page['file']); 6751f7a99c4SMichael Klier 6761f7a99c4SMichael Klier // show only a given section? 6771f7a99c4SMichael Klier if ($this->page['section'] && $this->page['exists']) $this->_getSection(); 6781f7a99c4SMichael Klier 6791f7a99c4SMichael Klier // convert relative links 6801f7a99c4SMichael Klier $this->_convertInstructions(); 6811f7a99c4SMichael Klier 6821f7a99c4SMichael Klier // render the included page 6831f7a99c4SMichael Klier $backupID = $ID; // store the current ID 6841f7a99c4SMichael Klier $ID = $this->page['id']; // change ID to the included page 6851f7a99c4SMichael Klier // remove document_start and document_end to avoid zipping 6861f7a99c4SMichael Klier $this->ins = array_slice($this->ins, 1, -1); 6871f7a99c4SMichael Klier p_render('odt', $this->ins, $info); 6881f7a99c4SMichael Klier $ID = $backupID; // restore ID 6891f7a99c4SMichael Klier // reset defaults 6901f7a99c4SMichael Klier $this->helper_plugin_include(); 6911f7a99c4SMichael Klier } 692f9f65fc3Swikidesign} 693df4e907bSMichael Klier//vim:ts=4:sw=4:et:enc=utf-8: 694