/** * Go through the list of moves and find the new value for the given old ID * * @param string $old the old, full qualified ID * @param string $type 'media' or 'page' * @throws Exception on bad argument * @return string the new full qualified ID */ public function resolveMoves($old, $type) { global $conf; if ($type != 'media' && $type != 'page') { throw new Exception('Not a valid type'); } $old = resolve_id($this->origNS, $old, false); if ($type == 'page') { // FIXME this simply assumes that the link pointed to :$conf['start'], but it could also point to another page // resolve_pageid does a lot more here, but we can't really assume this as the original pages might have been // deleted already if (substr($old, -1) === ':') { $old .= $conf['start']; } $moves = $this->page_moves; } else { $moves = $this->media_moves; } $old = cleanID($old); foreach ($moves as $move) { if ($move[0] == $old) { $old = $move[1]; } } return $old; // this is now new }
function test1() { // we test multiple cases here // format: $ns, $page, $output $tests = array(); // relative current in root $tests[] = array('', 'page', 'page'); $tests[] = array('', '.page', 'page'); $tests[] = array('', '.:page', 'page'); // relative current in namespace $tests[] = array('lev1:lev2', 'page', 'lev1:lev2:page'); $tests[] = array('lev1:lev2', '.page', 'lev1:lev2:page'); $tests[] = array('lev1:lev2', '.:page', 'lev1:lev2:page'); // relative upper in root $tests[] = array('', '..page', 'page'); $tests[] = array('', '..:page', 'page'); // relative upper in namespace $tests[] = array('lev1:lev2', '..page', 'lev1:page'); $tests[] = array('lev1:lev2', '..:page', 'lev1:page'); $tests[] = array('lev1:lev2', '..:..:page', 'page'); $tests[] = array('lev1:lev2', '..:..:..:page', 'page'); // strange and broken ones $tests[] = array('lev1:lev2', '....:....:page', 'lev1:lev2:page'); $tests[] = array('lev1:lev2', '..:..:lev3:page', 'lev3:page'); $tests[] = array('lev1:lev2', '..:..:lev3:..:page', 'page'); $tests[] = array('lev1:lev2', '..:..:lev3:..:page:....:...', 'page'); foreach ($tests as $test) { $this->assertEqual(resolve_id($test[0], $test[1]), $test[2]); } }
/** * get a list of namespace / page files * * @param string $folder an already converted filesystem folder of the current namespace */ function getTree($folder = ':') { global $conf; global $ID; // read tree structure from pages and media $ofolder = $folder; if ($folder == '*' || $folder == '') { $folder = ':'; } if ($folder[0] != ':') { $folder = resolve_id($folder, $ID); } $dir = strtr(cleanID($folder), ':', '/'); if (!($this->cache() && is_array($data = $this->cache()->get('explorertree_cache_' . $dir)))) { $data = array(); search($data, $conf['datadir'], 'search_index', array('ns' => getNS($ID)), $dir, $dir == '' ? 1 : count(explode('/', $dir)) + 1); $count = count($data); if ($count > 0) { for ($i = 1; $i < $count; $i++) { if ($data[$i - 1]['id'] == $data[$i]['id'] && $data[$i - 1]['type'] == $data[$i]['type']) { unset($data[$i]); $i++; // duplicate found, next $i can't be a duplicate, so skip forward one } } } if ($this->cache()) { $this->cache()->set($cache_id = 'explorertree_cache_' . $dir, $data, 60); // store the data itself (cache for one minute) } } return $data; }
/** * When WRITE is triggered, and the content is empty * * @author Gerry Weissbach <*****@*****.**> * @author Jon Magne Bøe <*****@*****.**> */ function _daftdrafts_write(&$event, $param) { global $INFO; if (empty($event->data[0][1])) { $id = resolve_id($event->data[1], $event->data[2]); $this->_daftdrafts_del_acl($id); $INFO['perm'] = $this->_auth_quickaclcheck($id); } }
/** * Handle the match */ function handle($match, $state, $pos, Doku_Handler $handler) { global $ID; $match = substr($match, 10, -2); //strip markup from start and end $data = array(); // extract params list($ns, $params) = explode(' ', $match, 2); $ns = trim($ns); // namespace (including resolving relatives) $data['ns'] = resolve_id(getNS($ID), $ns); $data['skin'] = 'original'; // alignment $data['align'] = 'left'; if (preg_match('/\\bleft\\b/i', $params)) { $data['align'] = 'left'; $params = preg_replace('/\\bleft\\b/i', '', $params); } if (preg_match('/\\bcenter\\b/i', $params)) { $data['align'] = 'center'; $params = preg_replace('/\\bcenter\\b/i', '', $params); } if (preg_match('/\\bright\\b/i', $params)) { $data['align'] = 'right'; $params = preg_replace('/\\bright\\b/i', '', $params); } $data['shuffle'] = false; if (preg_match('/\\bshuffle\\b/i', $params)) { $data['shuffle'] = true; $params = preg_replace('/\\bshuffle\\b/i', '', $params); } $data['repeat'] = false; if (preg_match('/\\brepeat\\b/i', $params)) { $data['repeat'] = true; $params = preg_replace('/\\brepeat\\b/i', '', $params); } $data['autoplay'] = false; if (preg_match('/\\bautoplay\\b/i', $params)) { $data['autoplay'] = true; $params = preg_replace('/\\bautoplay\\b/i', '', $params); } // the rest is the skin $data['skin'] = trim($params); list($data['skin'], $data['width'], $data['height']) = $this->_skininfo($data['skin']); return $data; }
/** * Go through the list of moves and find the new value for the given old ID * * @param string $old the old, full qualified ID * @param string $type 'media' or 'page' * @throws Exception on bad argument * @return string the new full qualified ID */ public function resolveMoves($old, $type) { global $conf; if ($type != 'media' && $type != 'page') { throw new Exception('Not a valid type'); } if ($conf['useslash']) { $old = str_replace('/', ':', $old); $delimiter = '/'; } else { $delimiter = ':'; } $old = resolve_id($this->origNS, $old, false); if ($type == 'page') { // FIXME this simply assumes that the link pointed to :$conf['start'], but it could also point to another page // resolve_pageid does a lot more here, but we can't really assume this as the original pages might have been // deleted already if (substr($old, -1) === ':') { $old .= $conf['start']; } $old = cleanID($old); $moves = $this->page_moves; } else { $moves = $this->media_moves; } if (substr($old, 0, 1) !== $delimiter) { $tempColon = true; $old = $delimiter . $old; } foreach ($moves as $move) { if (substr($move[0], 0, 1) !== $delimiter) { $move[0] = $delimiter . $move[0]; } if ($move[0] == $old) { $old = $move[1]; if (substr($old, 0, 1) !== $delimiter) { $old = $delimiter . $old; } } } if (isset($tempColon) && $tempColon) { $old = substr($old, 1); } return $old; // this is now new }
/** * Handle the match */ function handle($match, $state, $pos, Doku_Handler $handler) { global $ID; $data = array('width' => 500, 'height' => 250, 'align' => 0, 'initialZoom' => 1, 'tileBaseUri' => DOKU_BASE . 'lib/plugins/panoview/tiles.php', 'tileSize' => 256, 'maxZoom' => 10, 'blankTile' => DOKU_BASE . 'lib/plugins/panoview/gfx/blank.gif', 'loadingTile' => DOKU_BASE . 'lib/plugins/panoview/gfx/progress.gif'); $match = substr($match, 11, -2); //strip markup from start and end // alignment $data['align'] = 0; if (substr($match, 0, 1) == ' ') { $data['align'] += 1; } if (substr($match, -1, 1) == ' ') { $data['align'] += 2; } // extract params list($img, $params) = explode('?', $match, 2); $img = trim($img); // resolving relatives $data['image'] = resolve_id(getNS($ID), $img); $file = mediaFN($data['image']); list($data['imageWidth'], $data['imageHeight']) = @getimagesize($file); // calculate maximum zoom $data['maxZoom'] = ceil(sqrt(max($data['imageWidth'], $data['imageHeight']) / $data['tileSize'])); // size if (preg_match('/\\b(\\d+)[xX](\\d+)\\b/', $params, $match)) { $data['width'] = $match[1]; $data['height'] = $match[2]; } // initial zoom if (preg_match('/\\b[zZ](\\d+)\\b/', $params, $match)) { $data['initialZoom'] = $match[1]; } if ($data['initialZoom'] < 0) { $data['initialZoom'] = 0; } if ($data['initialZoom'] > $data['maxZoom']) { $data['initialZoom'] = $data['maxZoom']; } return $data; }
/** * Returns a full page id * * @author Andreas Gohr <*****@*****.**> */ function resolve_pageid($ns, &$page, &$exists) { global $conf; $exists = false; //keep hashlink if exists then clean both parts if (strpos($page, '#')) { list($page, $hash) = explode('#', $page, 2); } else { $hash = ''; } $hash = cleanID($hash); $page = resolve_id($ns, $page, false); // resolve but don't clean, yet // get filename (calls clean itself) $file = wikiFN($page); // if ends with colon or slash we have a namespace link if (in_array(substr($page, -1), array(':', ';')) || $conf['useslash'] && substr($page, -1) == '/') { if (page_exists($page . $conf['start'])) { // start page inside namespace $page = $page . $conf['start']; $exists = true; } elseif (page_exists($page . noNS(cleanID($page)))) { // page named like the NS inside the NS $page = $page . noNS(cleanID($page)); $exists = true; } elseif (page_exists($page)) { // page like namespace exists $page = $page; $exists = true; } else { // fall back to default $page = $page . $conf['start']; } } else { //check alternative plural/nonplural form if (!@file_exists($file)) { if ($conf['autoplural']) { if (substr($page, -1) == 's') { $try = substr($page, 0, -1); } else { $try = $page . 's'; } if (page_exists($try)) { $page = $try; $exists = true; } } } else { $exists = true; } } // now make sure we have a clean page $page = cleanID($page); //add hash if any if (!empty($hash)) { $page .= '#' . $hash; } }
/** * Parse out the namespace, and convert to a regex for array search * * @param string $query user page query * @return string processed query with necessary regex markup for namespace recognition */ function parse_ns_query($query) { global $INFO; $cur_ns = $INFO['namespace']; $incl_ns = array(); $excl_ns = array(); $page_qry = ''; $tokens = explode(' ', trim($query)); if (count($tokens) == 1) { $page_qry = $query; } else { foreach ($tokens as $token) { if (preg_match('/^(?:\\^|-ns:)(.+)$/u', $token, $matches)) { $excl_ns[] = resolve_id($cur_ns, $matches[1]); // also resolve relative and parent ns } elseif (preg_match('/^(?:@|ns:)(.+)$/u', $token, $matches)) { $incl_ns[] = resolve_id($cur_ns, $matches[1]); } else { $page_qry .= ' ' . $token; } } } $page_qry = trim($page_qry); return array($page_qry, $incl_ns, $excl_ns); }
/** * Adapts a link respecting all moves and making it a relative link according to the new id * * @param string $id A relative id * @param bool $media If the id is a media id * @return string The relative id, adapted according to the new/old id and the moves */ public function adaptRelativeId($id, $media = false) { global $conf; if ($id === '') { return $id; } $abs_id = str_replace('/', ':', $id); $abs_id = resolve_id($this->ns, $abs_id, false); if (substr($abs_id, -1) === ':') $abs_id .= $conf['start']; $clean_id = cleanID($abs_id); // FIXME this simply assumes that the link pointed to :$conf['start'], but it could also point to another page // resolve_pageid does a lot more here, but we can't really assume this as the original pages might have been // deleted already if (substr($clean_id, -1) === ':') $clean_id .= $conf['start']; if (($media ? isset($this->media_moves[$clean_id]) : isset($this->moves[$clean_id])) || $this->ns !== $this->new_ns) { if (!$media && isset($this->moves[$clean_id])) { $new = $this->moves[$clean_id]; } elseif ($media && isset($this->media_moves[$clean_id])) { $new = $this->media_moves[$clean_id]; } else { $new = $clean_id; // only the namespace was changed so if the link still resolves to the same absolute id, we can skip the rest $new_abs_id = str_replace('/', ':', $id); $new_abs_id = resolve_id($this->new_ns, $new_abs_id, false); if (substr($new_abs_id, -1) === ':') $new_abs_id .= $conf['start']; if ($new_abs_id == $abs_id) return $id; } $new_link = $new; $new_ns = getNS($new); // try to keep original pagename if ($this->noNS($new) == $this->noNS($clean_id)) { if ($new_ns == $this->new_ns) { $new_link = $this->noNS($id); if ($new_link === false) $new_link = $this->noNS($new); if ($id == ':') $new_link = ':'; else if ($id == '/') $new_link = '/'; } else if ($new_ns != false) { $new_link = $new_ns.':'.$this->noNS($id); } else { $new_link = $this->noNS($id); if ($new_link === false) $new_link = $new; } } else if ($new_ns == $this->new_ns) { $new_link = $this->noNS($new_link); } else if (strpos($new_ns, $this->ns.':') === 0) { $new_link = '.:'.substr($new_link, strlen($this->ns)+1); } if ($this->new_ns != '' && $new_ns == false) { $new_link = ':'.$new_link; } return $new_link; } else { return $id; } }
/** * Handle the match */ function handle($match, $state, $pos, &$handler) { global $ID; $match = substr($match, 10, -2); //strip markup from start and end $data = array(); $data['galid'] = substr(md5($match), 0, 4); // alignment $data['align'] = 0; if (substr($match, 0, 1) == ' ') { $data['align'] += 1; } if (substr($match, -1, 1) == ' ') { $data['align'] += 2; } // extract params list($ns, $params) = explode('?', $match, 2); $ns = trim($ns); // namespace (including resolving relatives) if (preg_match('/^(https?)|facebook:\\/\\//i', $ns)) { $data['ns'] = $ns; } else { $data['ns'] = resolve_id(getNS($ID), $ns); } // set the defaults $data['tw'] = $this->getConf('thumbnail_width'); $data['th'] = $this->getConf('thumbnail_height'); $data['iw'] = $this->getConf('image_width'); $data['ih'] = $this->getConf('image_height'); $data['cols'] = $this->getConf('cols'); $data['filter'] = ''; $data['lightbox'] = false; $data['fancybox'] = false; $data['fancyslideshow'] = false; $data['cyclepics'] = false; $data['direct'] = false; $data['page'] = false; $data['page_trimnumbers'] = false; $data['page_useid'] = false; $data['showname'] = false; $data['showtitle'] = false; $data['reverse'] = false; $data['random'] = false; $data['cache'] = true; $data['crop'] = false; $data['recursive'] = true; $data['sort'] = $this->getConf('sort'); $data['limit'] = 0; $data['offset'] = 0; $data['paginate'] = 0; // parse additional options $params = $this->getConf('options') . ',' . $params; $params = preg_replace('/[,&\\?]+/', ' ', $params); $params = explode(' ', $params); foreach ($params as $param) { if ($param === '') { continue; } if ($param == 'titlesort') { $data['sort'] = 'title'; } elseif ($param == 'datesort') { $data['sort'] = 'date'; } elseif ($param == 'modsort') { $data['sort'] = 'mod'; } elseif (preg_match('/^=(\\d+)$/', $param, $match)) { $data['limit'] = $match[1]; } elseif (preg_match('/^\\+(\\d+)$/', $param, $match)) { $data['offset'] = $match[1]; } elseif (is_numeric($param)) { $data['cols'] = (int) $param; } elseif (preg_match('/^~(\\d+)$/', $param, $match)) { $data['paginate'] = $match[1]; } elseif (preg_match('/^(\\d+)([xX])(\\d+)$/', $param, $match)) { if ($match[2] == 'X') { $data['iw'] = $match[1]; $data['ih'] = $match[3]; } else { $data['tw'] = $match[1]; $data['th'] = $match[3]; } } elseif (strpos($param, '*') !== false) { $param = preg_quote($param, '/'); $param = '/^' . str_replace('\\*', '.*?', $param) . '$/'; $data['filter'] = $param; } else { if (substr($param, 0, 2) == 'no') { $data[substr($param, 2)] = false; } else { $data[$param] = true; } } } // implicit direct linking? if ($data['lightbox']) { $data['direct'] = true; } #if($data['fancybox']) $data['direct'] = true; #if($data['fancyslideshow']) $data['direct'] = true; //Implicit page linking if using advanced page linking if ($data['page_useid'] || $data['page_trimnumbers']) { $data['page'] = true; } if ($data['page'] && auth_quickaclcheck($ID) >= AUTH_EDIT) { $data['cache'] = false; } return $data; }
/** * Create output */ function render($format, &$R, $data) { global $conf; global $lang; global $ID; if ($format != 'xhtml') { return false; } $opts = array('depth' => $data['depth'], 'listfiles' => true, 'listdirs' => false, 'pagesonly' => true, 'firsthead' => true, 'meta' => true); if ($data['dirs']) { $opts['listdirs'] = true; if ($data['files']) { $opts['listfiles'] = true; } else { $opts['listfiles'] = false; } } // read the directory $result = array(); search($result, $conf['datadir'], 'search_universal', $opts, $data['dir']); if ($data['fsort']) { usort($result, array($this, '_sort_file')); } elseif ($data['dsort']) { usort($result, array($this, '_sort_date')); } else { usort($result, array($this, '_sort_page')); } $start = cleanID($data['ns'] . ':' . $conf['start']); $R->listu_open(); foreach ($result as $item) { $skip_it = false; if ($data['nostart'] and $item['file'] == $conf['start'] . '.txt') { $skip_it = true; } else { if (!$data['me'] and $item['id'] == $ID) { $skip_it = true; } else { if (isHiddenPage($item['id'])) { $skip_it = true; } else { if ($item['type'] == 'd') { $P = resolve_id($item['id'], $conf['start'], false); if (!$data['any'] and !page_exists($P)) { $skip_it = true; } } else { $P = ':' . $item['id']; } } } } if (!$skip_it) { $R->listitem_open(1); $R->listcontent_open(); $R->internallink($P); if ($data['date']) { $R->cdata(' ' . dformat($item['mtime'])); } $R->listcontent_close(); $R->listitem_close(); } } $R->listu_close(); return true; }
/** * */ function _getNamespace() { if (!isset($_REQUEST['namespace'])) { throw new Exception('err_invreq'); } $namespace = trim($_REQUEST['namespace']); if ($namespace != '') { global $ID; $namespace = resolve_id(getNS($ID), $namespace . ':'); if ($namespace != '') { $namespace .= ':'; } } return $namespace; }
/** * Converts instructions of the included page * * The funcion iterates over the given list of instructions and generates * an index of header and section indicies. It also removes document * start/end instructions, converts links, and removes unwanted * instructions like tags, comments, linkbacks. * * Later all header/section levels are convertet to match the current * inclusion level. * * @author Michael Klier <*****@*****.**> */ function _convert_instructions(&$ins, $lvl, $page, $sect, $flags, $root_id) { global $conf; // filter instructions if needed if (!empty($sect)) { $this->_get_section($ins, $sect); // section required } if ($flags['firstsec']) { $this->_get_firstsec($ins, $page); // only first section } $ns = getNS($page); $num = count($ins); $conv_idx = array(); // conversion index $lvl_max = false; // max level $first_header = -1; $no_header = false; $sect_title = false; for ($i = 0; $i < $num; $i++) { switch ($ins[$i][0]) { case 'document_start': case 'document_end': case 'section_edit': unset($ins[$i]); break; case 'header': // get section title of first section if ($sect && !$sect_title) { $sect_title = $ins[$i][1][0]; } // check if we need to skip the first header if (!$no_header && $flags['noheader']) { $no_header = true; } $conv_idx[] = $i; // get index of first header if ($first_header == -1) { $first_header = $i; } // get max level of this instructions set if (!$lvl_max || $ins[$i][1][1] < $lvl_max) { $lvl_max = $ins[$i][1][1]; } break; case 'section_open': if ($flags['inline']) { unset($ins[$i]); } else { $conv_idx[] = $i; } break; case 'section_close': if ($flags['inline']) { unset($ins[$i]); } case 'internallink': case 'internalmedia': // make sure parameters aren't touched $link_params = ''; $link_id = $ins[$i][1][0]; $link_parts = explode('?', $link_id, 2); if (count($link_parts) === 2) { $link_id = $link_parts[0]; $link_params = $link_parts[1]; } // resolve the id without cleaning it $link_id = resolve_id($ns, $link_id, false); // this id is internal (i.e. absolute) now, add ':' to make resolve_id work again if ($link_id[0] != ':') { $link_id = ':' . $link_id; } // restore parameters $ins[$i][1][0] = $link_params != '' ? $link_id . '?' . $link_params : $link_id; break; case 'plugin': // FIXME skip other plugins? switch ($ins[$i][1][0]) { case 'tag_tag': // skip tags // skip tags case 'discussion_comments': // skip comments // skip comments case 'linkback': // skip linkbacks // skip linkbacks case 'data_entry': // skip data plugin // skip data plugin case 'meta': // skip meta plugin unset($ins[$i]); break; // adapt indentation level of nested includes // adapt indentation level of nested includes case 'include_include': if (!$flags['inline'] && $flags['indent']) { $ins[$i][1][1][4] += $lvl; } break; } break; default: break; } } // calculate difference between header/section level and include level $diff = 0; if (!isset($lvl_max)) { $lvl_max = 0; } // if no level found in target, set to 0 $diff = $lvl - $lvl_max + 1; if ($no_header) { $diff -= 1; } // push up one level if "noheader" // convert headers and set footer/permalink $hdr_deleted = false; $has_permalink = false; $footer_lvl = false; $contains_secedit = false; $section_close_at = false; foreach ($conv_idx as $idx) { if ($ins[$idx][0] == 'header') { if ($section_close_at === false) { // store the index of the first heading (the begin of the first section) $section_close_at = $idx; } if ($no_header && !$hdr_deleted) { unset($ins[$idx]); $hdr_deleted = true; continue; } if ($flags['indent']) { $lvl_new = $ins[$idx][1][1] + $diff > 5 ? 5 : $ins[$idx][1][1] + $diff; $ins[$idx][1][1] = $lvl_new; } if ($ins[$idx][1][1] <= $conf['maxseclevel']) { $contains_secedit = true; } // set permalink if ($flags['link'] && !$has_permalink && $idx == $first_header) { $this->_permalink($ins[$idx], $page, $sect, $flags); $has_permalink = true; } // set footer level if (!$footer_lvl && $idx == $first_header && !$no_header) { if ($flags['indent']) { $footer_lvl = $lvl_new; } else { $footer_lvl = $lvl_max; } } } else { // it's a section if ($flags['indent']) { $lvl_new = $ins[$idx][1][0] + $diff > 5 ? 5 : $ins[$idx][1][0] + $diff; $ins[$idx][1][0] = $lvl_new; } // check if noheader is used and set the footer level to the first section if ($no_header && !$footer_lvl) { if ($flags['indent']) { $footer_lvl = $lvl_new; } else { $footer_lvl = $lvl_max; } } } } // close last open section of the included page if there is any if ($contains_secedit) { array_push($ins, array('plugin', array('include_close_last_secedit', array()))); } // add edit button if ($flags['editbtn']) { $perm = auth_quickaclcheck($page); $can_edit = page_exists($page) ? $perm >= AUTH_EDIT : $perm >= AUTH_CREATE; if ($can_edit) { $this->_editbtn($ins, $page, $sect, $sect_title, $flags['redirect'] ? $root_id : false); } } // add footer if ($flags['footer']) { $ins[] = $this->_footer($page, $sect, $sect_title, $flags, $footer_lvl, $root_id); } // wrap content at the beginning of the include that is not in a section in a section if ($lvl > 0 && $section_close_at !== 0 && $flags['indent'] && !$flags['inline']) { if ($section_close_at === false) { $ins[] = array('section_close', array()); array_unshift($ins, array('section_open', array($lvl))); } else { $section_close_idx = array_search($section_close_at, array_keys($ins)); if ($section_close_idx > 0) { $before_ins = array_slice($ins, 0, $section_close_idx); $after_ins = array_slice($ins, $section_close_idx); $ins = array_merge($before_ins, array(array('section_close', array())), $after_ins); array_unshift($ins, array('section_open', array($lvl))); } } } // add instructions entry wrapper array_unshift($ins, array('plugin', array('include_wrap', array('open', $page, $flags['redirect'])))); array_push($ins, array('plugin', array('include_wrap', array('close')))); // close previous section if any and re-open after inclusion if ($lvl != 0 && $this->sec_close && !$flags['inline']) { array_unshift($ins, array('section_close', array())); $ins[] = array('section_open', array($lvl)); } }
/** * Returns a full page id * * @author Andreas Gohr <*****@*****.**> * * @param string $ns namespace which is context of id * @param string &$page (reference) relative page id, updated to resolved id * @param bool &$exists (reference) updated with existance of media */ function resolve_pageid($ns, &$page, &$exists, $rev = '', $date_at = false) { global $conf; global $ID; $exists = false; //empty address should point to current page if ($page === "") { $page = $ID; } //keep hashlink if exists then clean both parts if (strpos($page, '#')) { list($page, $hash) = explode('#', $page, 2); } else { $hash = ''; } $hash = cleanID($hash); $page = resolve_id($ns, $page, false); // resolve but don't clean, yet // get filename (calls clean itself) if ($rev !== '' && $date_at) { $pagelog = new PageChangeLog($page); $pagelog_rev = $pagelog->getLastRevisionAt($rev); if ($pagelog_rev !== false) { //something found $rev = $pagelog_rev; } } $file = wikiFN($page, $rev); // if ends with colon or slash we have a namespace link if (in_array(substr($page, -1), array(':', ';')) || $conf['useslash'] && substr($page, -1) == '/') { if (page_exists($page . $conf['start'], $rev, true, $date_at)) { // start page inside namespace $page = $page . $conf['start']; $exists = true; } elseif (page_exists($page . noNS(cleanID($page)), $rev, true, $date_at)) { // page named like the NS inside the NS $page = $page . noNS(cleanID($page)); $exists = true; } elseif (page_exists($page, $rev, true, $date_at)) { // page like namespace exists $page = $page; $exists = true; } else { // fall back to default $page = $page . $conf['start']; } } else { //check alternative plural/nonplural form if (!@file_exists($file)) { if ($conf['autoplural']) { if (substr($page, -1) == 's') { $try = substr($page, 0, -1); } else { $try = $page . 's'; } if (page_exists($try, $rev, true, $date_at)) { $page = $try; $exists = true; } } } else { $exists = true; } } // now make sure we have a clean page $page = cleanID($page); //add hash if any if (!empty($hash)) { $page .= '#' . $hash; } }
/** * Converts instructions of the included page * * The funcion iterates over the given list of instructions and generates * an index of header and section indicies. It also removes document * start/end instructions, converts links, and removes unwanted * instructions like tags, comments, linkbacks. * * Later all header/section levels are convertet to match the current * inclusion level. * * @author Michael Klier <*****@*****.**> */ function _convert_instructions(&$ins, $lvl, $page, $sect, $flags, $root_id, $included_pages = array()) { global $conf; // filter instructions if needed if(!empty($sect)) { $this->_get_section($ins, $sect); // section required } if($flags['firstsec']) { $this->_get_firstsec($ins, $page); // only first section } $ns = getNS($page); $num = count($ins); $conv_idx = array(); // conversion index $lvl_max = false; // max level $first_header = -1; $no_header = false; $sect_title = false; $endpos = null; // end position of the raw wiki text for($i=0; $i<$num; $i++) { // adjust links with image titles if (strpos($ins[$i][0], 'link') !== false && isset($ins[$i][1][1]) && is_array($ins[$i][1][1])) { // resolve relative ids, but without cleaning in order to preserve the name $media_id = resolve_id($ns, $ins[$i][1][1]['src']); // make sure that after resolving the link again it will be the same link if ($media_id{0} != ':') $media_id = ':'.$media_id; $ins[$i][1][1]['src'] = $media_id; } switch($ins[$i][0]) { case 'document_start': case 'document_end': case 'section_edit': unset($ins[$i]); break; case 'header': // get section title of first section if($sect && !$sect_title) { $sect_title = $ins[$i][1][0]; } // check if we need to skip the first header if((!$no_header) && $flags['noheader']) { $no_header = true; } $conv_idx[] = $i; // get index of first header if($first_header == -1) $first_header = $i; // get max level of this instructions set if(!$lvl_max || ($ins[$i][1][1] < $lvl_max)) { $lvl_max = $ins[$i][1][1]; } break; case 'section_open': if ($flags['inline']) unset($ins[$i]); else $conv_idx[] = $i; break; case 'section_close': if ($flags['inline']) unset($ins[$i]); break; case 'internallink': case 'internalmedia': // make sure parameters aren't touched $link_params = ''; $link_id = $ins[$i][1][0]; $link_parts = explode('?', $link_id, 2); if (count($link_parts) === 2) { $link_id = $link_parts[0]; $link_params = $link_parts[1]; } // resolve the id without cleaning it $link_id = resolve_id($ns, $link_id, false); // this id is internal (i.e. absolute) now, add ':' to make resolve_id work again if ($link_id{0} != ':') $link_id = ':'.$link_id; // restore parameters $ins[$i][1][0] = ($link_params != '') ? $link_id.'?'.$link_params : $link_id; if ($ins[$i][0] == 'internallink' && !empty($included_pages)) { // change links to included pages into local links $link_id = $ins[$i][1][0]; $link_parts = explode('?', $link_id, 2); // only adapt links without parameters if (count($link_parts) === 1) { $link_parts = explode('#', $link_id, 2); $hash = ''; if (count($link_parts) === 2) { list($link_id, $hash) = $link_parts; } $exists = false; resolve_pageid($ns, $link_id, $exists); if (array_key_exists($link_id, $included_pages)) { if ($hash) { // hopefully the hash is also unique in the including page (otherwise this might be the wrong link target) $ins[$i][0] = 'locallink'; $ins[$i][1][0] = $hash; } else { // the include section ids are different from normal section ids (so they won't conflict) but this // also means that the normal locallink function can't be used $ins[$i][0] = 'plugin'; $ins[$i][1] = array('include_locallink', array($included_pages[$link_id]['hid'], $ins[$i][1][1], $ins[$i][1][0])); } } } } break; case 'locallink': /* Convert local links to internal links if the page hasn't been fully included */ if ($included_pages == null || !array_key_exists($page, $included_pages)) { $ins[$i][0] = 'internallink'; $ins[$i][1][0] = ':'.$page.'#'.$ins[$i][1][0]; } break; case 'plugin': // FIXME skip other plugins? switch($ins[$i][1][0]) { case 'tag_tag': // skip tags case 'discussion_comments': // skip comments case 'linkback': // skip linkbacks case 'data_entry': // skip data plugin case 'meta': // skip meta plugin case 'indexmenu_tag': // skip indexmenu sort tag case 'include_sorttag': // skip include plugin sort tag unset($ins[$i]); break; // adapt indentation level of nested includes case 'include_include': if (!$flags['inline'] && $flags['indent']) $ins[$i][1][1][4] += $lvl; break; /* * if there is already a closelastsecedit instruction (was added by one of the section * functions), store its position but delete it as it can't be determined yet if it is needed, * i.e. if there is a header which generates a section edit (depends on the levels, level * adjustments, $no_header, ...) */ case 'include_closelastsecedit': $endpos = $ins[$i][1][1][0]; unset($ins[$i]); break; } break; default: break; } } // calculate difference between header/section level and include level $diff = 0; if (!isset($lvl_max)) $lvl_max = 0; // if no level found in target, set to 0 $diff = $lvl - $lvl_max + 1; if ($no_header) $diff -= 1; // push up one level if "noheader" // convert headers and set footer/permalink $hdr_deleted = false; $has_permalink = false; $footer_lvl = false; $contains_secedit = false; $section_close_at = false; foreach($conv_idx as $idx) { if($ins[$idx][0] == 'header') { if ($section_close_at === false) { // store the index of the first heading (the begin of the first section) $section_close_at = $idx; } if($no_header && !$hdr_deleted) { unset ($ins[$idx]); $hdr_deleted = true; continue; } if($flags['indent']) { $lvl_new = (($ins[$idx][1][1] + $diff) > 5) ? 5 : ($ins[$idx][1][1] + $diff); $ins[$idx][1][1] = $lvl_new; } if($ins[$idx][1][1] <= $conf['maxseclevel']) $contains_secedit = true; // set permalink if($flags['link'] && !$has_permalink && ($idx == $first_header)) { $this->_permalink($ins[$idx], $page, $sect, $flags); $has_permalink = true; } // set footer level if(!$footer_lvl && ($idx == $first_header) && !$no_header) { if($flags['indent']) { $footer_lvl = $lvl_new; } else { $footer_lvl = $lvl_max; } } } else { // it's a section if($flags['indent']) { $lvl_new = (($ins[$idx][1][0] + $diff) > 5) ? 5 : ($ins[$idx][1][0] + $diff); $ins[$idx][1][0] = $lvl_new; } // check if noheader is used and set the footer level to the first section if($no_header && !$footer_lvl) { if($flags['indent']) { $footer_lvl = $lvl_new; } else { $footer_lvl = $lvl_max; } } } } // close last open section of the included page if there is any if ($contains_secedit) { array_push($ins, array('plugin', array('include_closelastsecedit', array($endpos)))); } // add edit button if($flags['editbtn']) { $this->_editbtn($ins, $page, $sect, $sect_title, ($flags['redirect'] ? $root_id : false)); } // add footer if($flags['footer']) { $ins[] = $this->_footer($page, $sect, $sect_title, $flags, $footer_lvl, $root_id); } // wrap content at the beginning of the include that is not in a section in a section if ($lvl > 0 && $section_close_at !== 0 && $flags['indent'] && !$flags['inline']) { if ($section_close_at === false) { $ins[] = array('section_close', array()); array_unshift($ins, array('section_open', array($lvl))); } else { $section_close_idx = array_search($section_close_at, array_keys($ins)); if ($section_close_idx > 0) { $before_ins = array_slice($ins, 0, $section_close_idx); $after_ins = array_slice($ins, $section_close_idx); $ins = array_merge($before_ins, array(array('section_close', array())), $after_ins); array_unshift($ins, array('section_open', array($lvl))); } } } // add instructions entry wrapper $include_secid = (isset($flags['include_secid']) ? $flags['include_secid'] : NULL); array_unshift($ins, array('plugin', array('include_wrap', array('open', $page, $flags['redirect'], $include_secid)))); if (isset($flags['beforeeach'])) array_unshift($ins, array('entity', array($flags['beforeeach']))); array_push($ins, array('plugin', array('include_wrap', array('close')))); if (isset($flags['aftereach'])) array_push($ins, array('entity', array($flags['aftereach']))); // close previous section if any and re-open after inclusion if($lvl != 0 && $this->sec_close && !$flags['inline']) { array_unshift($ins, array('section_close', array())); $ins[] = array('section_open', array($lvl)); } }
/** * Parse namespace request * * @author Samuele Tognini <*****@*****.**> */ function _parse_ns($ns, $id = FALSE) { if (!$id) { global $ID; $id = $ID; } //Just for old reelases compatibility if (empty($ns) || $ns == '..') { $ns = ":.."; } return resolve_id(getNS($id), $ns); }