public function test_numeric_twice_meta() { $indexer = idx_get_indexer(); $indexer->addMetaKeys('testpage', 'onezero', array('1010')); $indexer->addMetaKeys('notfound', 'onezero', array('1010')); $query = '1010'; $this->assertEquals(array('notfound', 'testpage'), $indexer->lookupKey('onezero', $query)); }
function setUp() { parent::setUp(); $this->indexer = idx_get_indexer(); $this->indexer->clear(); saveWikiText($this->old_id, 'Old test content', 'Created old test page for indexer rename test'); idx_addPage($this->old_id); }
public function test_media_in_footnotes() { saveWikiText('test:media_footnotes', '(({{footnote.png?20x50}} [[foonote|{{:footlink.png}}]]))', 'Test initialization'); idx_addPage('test:media_footnotes'); $query = array('test:footnote.png', 'footlink.png'); $this->assertEquals(array( 'test:footnote.png' => array('test:media_footnotes'), 'footlink.png' => array('test:media_footnotes') ), idx_get_indexer()->lookupKey('relation_media', $query)); }
function test_minlength() { $indexer = idx_get_indexer(); $indexer->addMetaKeys('histo1', 'testkey', array('foo', 'bar', 'foobar')); $indexer->addMetaKeys('histo2', 'testkey', array('bar', 'testing')); $indexer->addMetaKeys('histo3', 'testkey', array('foo', 'foobar')); $histogram4 = $indexer->histogram(1, 0, 4, 'testkey'); $this->assertEquals(array('foobar' => 2, 'testing' => 1), $histogram4); $histogram2 = $indexer->histogram(1, 0, 2, 'testkey'); $this->assertEquals(array('foobar' => 2, 'testing' => 1, 'foo' => 2, 'bar' => 2), $histogram2); }
function test_pid() { $indexer = idx_get_indexer(); $syntaxPID = $indexer->getPID('wiki:syntax'); $this->assertEquals('wiki:syntax', $indexer->getPageFromPID($syntaxPID), 'getPageFromPID(getPID(\'wiki:syntax\')) != \'wiki:syntax\''); $dokuwikiPID = $indexer->getPID('wiki:dokuwiki'); $this->assertEquals('wiki:syntax', $indexer->getPageFromPID($syntaxPID), 'getPageFromPID(getPID(\'wiki:syntax\')) != \'wiki:syntax\' after getting the PID for wiki:dokuwiki'); $this->assertEquals($syntaxPID, $indexer->getPID('wiki:syntax'), 'getPID(\'wiki:syntax\') didn\'t returned different PIDs when called twice'); $this->assertNotEquals($syntaxPID, $dokuwikiPID, 'Same PID returned for different pages'); $this->assertTrue(is_numeric($syntaxPID) && is_numeric($dokuwikiPID), 'PIDs are not numeric'); }
function _update() { global $conf; global $INDEXER; $INDEXER = idx_get_indexer(); $data = array(); _quietecho("Searching pages... "); search($data, $conf['datadir'], 'search_allpages', array('skipacl' => true)); _quietecho(count($data) . " pages found.\n"); foreach ($data as $val) { _index($val['id']); } }
/** * Builds a Google Sitemap of all public pages known to the indexer * * The map is placed in the cache directory named sitemap.xml.gz - This * file needs to be writable! * * @author Michael Hamann * @author Andreas Gohr * @link https://www.google.com/webmasters/sitemaps/docs/en/about.html * @link http://www.sitemaps.org/ */ public function generate() { global $conf; if ($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) { return false; } $sitemap = Sitemapper::getFilePath(); if (@file_exists($sitemap)) { if (!is_writable($sitemap)) { return false; } } else { if (!is_writable(dirname($sitemap))) { return false; } } if (@filesize($sitemap) && @filemtime($sitemap) > time() - $conf['sitemap'] * 86400) { // 60*60*24=86400 dbglog('Sitemapper::generate(): Sitemap up to date'); // FIXME: only in debug mode return false; } dbglog("Sitemapper::generate(): using {$sitemap}"); // FIXME: Only in debug mode $pages = idx_get_indexer()->getPages(); dbglog('Sitemapper::generate(): creating sitemap using ' . count($pages) . ' pages'); $items = array(); // build the sitemap items foreach ($pages as $id) { //skip hidden, non existing and restricted files if (isHiddenPage($id)) { continue; } if (auth_aclcheck($id, '', '') < AUTH_READ) { continue; } $item = SitemapItem::createFromID($id); if ($item !== NULL) { $items[] = $item; } } $eventData = array('items' => &$items, 'sitemap' => &$sitemap); $event = new Doku_Event('SITEMAP_GENERATE', $eventData); if ($event->advise_before(true)) { //save the new sitemap $result = io_saveFile($sitemap, Sitemapper::getXML($items)); } $event->advise_after(); return $result; }
/** * Setup the data directory * * This is ran before each test class */ public static function setUpBeforeClass() { // just to be safe not to delete something undefined later if (!defined('TMP_DIR')) { die('no temporary directory'); } if (!defined('DOKU_TMP_DATA')) { die('no temporary data directory'); } // remove any leftovers from the last run if (is_dir(DOKU_TMP_DATA)) { // clear indexer data and cache idx_get_indexer()->clear(); TestUtils::rdelete(DOKU_TMP_DATA); } // populate default dirs TestUtils::rcopy(TMP_DIR, dirname(__FILE__) . '/../data/'); }
/** * Tag index lookup * * @param array $tags the tags to filter * @return array the matching page ids */ function _tagIndexLookup($tags) { $result = array(); // array of page ids $clean_tags = array(); foreach ($tags as $i => $tag) { if ($tag[0] == '+' || $tag[0] == '-') { $clean_tags[$i] = substr($tag, 1); } else { $clean_tags[$i] = $tag; } } $indexer = idx_get_indexer(); $pages = $indexer->lookupKey('subject', $clean_tags, array($this, '_tagCompare')); // use all pages as basis if the first tag isn't an "or"-tag or if there are no tags given if (empty($tags) || $clean_tags[0] != $tags[0]) { $result = $indexer->getPages(); } foreach ($tags as $i => $tag) { $t = $clean_tags[$i]; if (!is_array($pages[$t])) { $pages[$t] = array(); } if ($tag[0] == '+') { // AND: add only if in both arrays $result = array_intersect($result, $pages[$t]); } elseif ($tag[0] == '-') { // NOT: remove array from docs $result = array_diff($result, $pages[$t]); } else { // OR: add array to docs $result = array_unique(array_merge($result, $pages[$t])); } } return $result; }
function _ft_pageLookup(&$data) { // split out original parameters $id = $data['id']; if (preg_match('/(?:^| )@(\\w+)/', $id, $matches)) { $ns = cleanID($matches[1]) . ':'; $id = str_replace($matches[0], '', $id); } $in_ns = $data['in_ns']; $in_title = $data['in_title']; $cleaned = cleanID($id); $Indexer = idx_get_indexer(); $page_idx = $Indexer->getPages(); $pages = array(); if ($id !== '' && $cleaned !== '') { foreach ($page_idx as $p_id) { if (strpos($in_ns ? $p_id : noNSorNS($p_id), $cleaned) !== false) { if (!isset($pages[$p_id])) { $pages[$p_id] = p_get_first_heading($p_id, METADATA_DONT_RENDER); } } } if ($in_title) { foreach ($Indexer->lookupKey('title', $id, '_ft_pageLookupTitleCompare') as $p_id) { if (!isset($pages[$p_id])) { $pages[$p_id] = p_get_first_heading($p_id, METADATA_DONT_RENDER); } } } } if (isset($ns)) { foreach (array_keys($pages) as $p_id) { if (strpos($p_id, $ns) !== 0) { unset($pages[$p_id]); } } } // discard hidden pages // discard nonexistent pages // check ACL permissions foreach (array_keys($pages) as $idx) { if (!isVisiblePage($idx) || !page_exists($idx) || auth_quickaclcheck($idx) < AUTH_READ) { unset($pages[$idx]); } } uksort($pages, 'ft_pagesorter'); return $pages; }
/** * List all pages - we use the indexer list here */ function listPages() { $list = array(); $pages = idx_get_indexer()->getPages(); $pages = array_filter(array_filter($pages, 'isVisiblePage'), 'page_exists'); foreach (array_keys($pages) as $idx) { $perm = auth_quickaclcheck($pages[$idx]); if ($perm < AUTH_READ) { continue; } $page = array(); $page['id'] = trim($pages[$idx]); $page['perms'] = $perm; $page['size'] = @filesize(wikiFN($pages[$idx])); $page['lastModified'] = $this->api->toDate(@filemtime(wikiFN($pages[$idx]))); $list[] = $page; } return $list; }
/** * Split a string into tokens * */ function idx_tokenizer($string, $wc = false) { $Indexer = idx_get_indexer(); return $Indexer->tokenizer($string, $wc); }
/** * Clear all index files */ function clearindex() { $this->quietecho("Clearing index... "); idx_get_indexer()->clear(); $this->quietecho("done.\n"); }
/** * A heavily customised version of _ft_pageLookup in inc/fulltext.php * no sorting! */ function page_lookup($query, $fullregex, $incl_ns, $excl_ns) { global $conf; $query = trim($query); $pages = idx_get_indexer()->getPages(); if (!$fullregex) { // first deal with excluded namespaces, then included, order matters! $pages = $this->_filter_ns($pages, $excl_ns, true); $pages = $this->_filter_ns($pages, $incl_ns, false); } $cnt = count($pages); for ($i = 0; $i < $cnt; $i++) { $page = $pages[$i]; if (!page_exists($page) || isHiddenPage($page)) { unset($pages[$i]); continue; } if (!$fullregex) { $page = noNS($page); } /* * This is the actual "search" expression. * Note: preg_grep cannot be used because we need to * allow for beginning of string "^" regex on normal page search * and the page-exists check above * The @ prevents problems with invalid queries! */ $matched = @preg_match('/' . $query . '/iS', $page); if ($matched === false) { return false; } elseif ($matched == 0) { unset($pages[$i]); } } if (count($pages) > 0) { return $pages; } else { // we always return an array type return array(); } }
/** * Execute a media file move/rename * * @param string $src original ID * @param string $dst new ID * @return bool true if the move was successfully executed */ public function moveMedia($src, $dst) { if (!$this->checkMedia($src, $dst)) { return false; } // get all pages using this media $affected_pages = idx_get_indexer()->lookupKey('relation_media', $src); $src_ns = getNS($src); $src_name = noNS($src); $dst_ns = getNS($dst); $dst_name = noNS($dst); // pass this info on to other plugins $eventdata = array('opts' => array('ns' => $src_ns, 'name' => $src_name, 'newns' => $dst_ns, 'newname' => $dst_name), 'affected_pages' => &$affected_pages, 'src_id' => $src, 'dst_id' => $dst); // give plugins the option to add their own meta files to the list of files that need to be moved // to the oldfiles/newfiles array or to adjust their own metadata, database, ... // and to add other pages to the affected pages $event = new Doku_Event('PLUGIN_MOVE_MEDIA_RENAME', $eventdata); if ($event->advise_before()) { /** @var helper_plugin_move_file $FileMover */ $FileMover = plugin_load('helper', 'move_file'); /** @var helper_plugin_move_rewrite $Rewriter */ $Rewriter = plugin_load('helper', 'move_rewrite'); // Move the Subscriptions & Indexes (new feature since Spring 2013 release) $Indexer = idx_get_indexer(); if (($idx_msg = $Indexer->renameMetaValue('relation_media', $src, $dst)) !== true) { msg(sprintf($this->getLang('indexerror'), $idx_msg), -1); return false; } if (!$FileMover->moveMediaMeta($src_ns, $src_name, $dst_ns, $dst_name)) { msg(sprintf($this->getLang('mediametamoveerror'), $src), -1); return false; } // prepare directory io_createNamespace($dst, 'media'); // move it FIXME this does not create a changelog entry! if (!io_rename(mediaFN($src), mediaFN($dst))) { msg(sprintf($this->getLang('mediamoveerror'), $src), -1); return false; } // clean up old ns io_sweepNS($src, 'mediadir'); // Move the old revisions if (!$FileMover->moveMediaAttic($src_ns, $src_name, $dst_ns, $dst_name)) { // it's too late to stop the move, so just display a message. msg(sprintf($this->getLang('mediaatticmoveerror'), $src), -1); } // Add meta data to all affected pages, so links get updated later foreach ($affected_pages as $id) { $Rewriter->setMoveMeta($id, $src, $dst, 'media'); } } $event->advise_after(); // store this for later use $this->affectedPages = $affected_pages; return true; }
/** * Move media file * * @author Michael Hamann <*****@*****.**> * * @param array $opts * @param bool $checkonly Only execute the checks if the media file can be moved * @return bool If the move was executed */ public function move_media(&$opts, $checkonly = false) { $opts['id'] = cleanID($opts['ns'].':'.$opts['name']); $opts['path'] = mediaFN($opts['id']); // Check we have rights to move this document if ( !file_exists(mediaFN($opts['id']))) { msg(sprintf($this->getLang('medianotexist'), hsc($opts['id'])), -1); return false; } if ( auth_quickaclcheck($opts['ns'].':*') < AUTH_DELETE ) { msg(sprintf($this->getLang('nomediarights'), hsc($opts['id'])), -1); return false; } // Assemble media name and path $opts['new_id'] = cleanID($opts['newns'].':'.$opts['newname']); $opts['new_path'] = mediaFN($opts['new_id']); // Has the document name and/or namespace changed? if ( $opts['newns'] == $opts['ns'] && $opts['newname'] == $opts['name'] ) { msg($this->getLang('nomediachange'), -1); return false; } // Check the page does not already exist if ( @file_exists($opts['new_path']) ) { msg(sprintf($this->getLang('mediaexisting'), $opts['newname'], ($opts['newns'] == '' ? $this->getLang('root') : $opts['newns'])), -1); return false; } // Check if the current user can create the new page if (auth_quickaclcheck($opts['new_ns'].':*') < AUTH_UPLOAD) { msg(sprintf($this->getLang('nomediatargetperms'), $opts['new_id']), -1); return false; } if ($checkonly) return true; /** * End of init (checks) */ $affected_pages = idx_get_indexer()->lookupKey('relation_media', $opts['id']); $data = array('opts' => &$opts, 'affected_pages' => &$affected_pages); // give plugins the option to add their own meta files to the list of files that need to be moved // to the oldfiles/newfiles array or to adjust their own metadata, database, ... // and to add other pages to the affected pages $event = new Doku_Event('PLUGIN_MOVE_MEDIA_RENAME', $data); if ($event->advise_before()) { // Move the Subscriptions & Indexes if (method_exists('Doku_Indexer', 'renamePage')) { // new feature since Spring 2013 release $Indexer = idx_get_indexer(); } else { $Indexer = new helper_plugin_move_indexer(); // copy of the new code } if (($idx_msg = $Indexer->renameMetaValue('relation_media', $opts['id'], $opts['new_id'])) !== true) { msg('Error while updating the search index '.$idx_msg, -1); return false; } if (!$this->movemediameta($opts)) { msg('The meta files of the media file '.$opts['id'].' couldn\'t be moved', -1); return false; } // prepare directory io_createNamespace($opts['new_id'], 'media'); if (!io_rename($opts['path'], $opts['new_path'])) { msg('Moving the media file '.$opts['id'].' failed', -1); return false; } io_sweepNS($opts['id'], 'mediadir'); // Move the old revisions if (!$this->movemediaattic($opts)) { // it's too late to stop the move, so just display a message. msg('The attic files of media file '.$opts['id'].' couldn\'t be moved. Please move them manually.', -1); } foreach ($affected_pages as $id) { if (!page_exists($id, '', false)) continue; $meta = $this->getMoveMeta($id); if (!$meta) $meta = array('media_moves' => array()); if (!isset($meta['media_moves'])) $meta['media_moves'] = array(); $meta['media_moves'] = $this->resolve_moves($meta['media_moves'], '__'); $meta['media_moves'][$opts['id']] = $opts['new_id']; //if (empty($meta['moves'])) unset($meta['moves']); p_set_metadata($id, array('plugin_move' => $meta), false, true); } } $event->advise_after(); return true; }
function setUp() { parent::setUpBeforeClass(); $this->pluginsEnabled[] = 'move'; global $ID; global $INFO; global $conf; $ID = $this->movedId; $text = <<<EOT [[start|start]] [[parallel_page|parallel_page]] [[.:|.:]] [[..current_ns:|..current_ns:]] [[..:current_ns:|..:current_ns:]] [[..parallel_ns:|..parallel_ns:]] [[..:parallel_ns:|..:parallel_ns:]] [[..:..:|..:..:]] [[..:..:parent_ns:|..:..:parent_ns:]] [[parent_ns:new_page|parent_ns:new_page]] [[parent_ns/new_page|parent_ns/new_page]] [[/start|/start]] EOT; $summary = 'Test'; saveWikiText($this->movedId, $text, $summary); $INFO = pageinfo(); $references = array_keys(p_get_metadata($this->movedId, 'relation references', METADATA_RENDER_UNLIMITED)); idx_get_indexer()->addMetaKeys($this->movedId, 'relation_references', $references); $text = <<<EOT [[{$this->movedId}|{$this->movedId}]] [[:{$this->movedId}|:{$this->movedId}]] [[.current_ns:test_page|.current_ns:test_page]] [[.:current_ns:test_page|.:current_ns:test_page]] [[..parent_ns:current_ns:test_page|..parent_ns:current_ns:test_page]] [[test_page|test_page]] [[new_page|new_page]] [[ftp://somewhere.com|ftp://somewhere.com]] [[http://somewhere.com|http://somewhere.com]] [[start|start]] [[parallel_page|parallel_page]] [[.:|.:]] [[..current_ns:|..current_ns:]] [[..:current_ns:|..:current_ns:]] [[..parallel_ns:|..parallel_ns:]] [[..:parallel_ns:|..:parallel_ns:]] [[..:..:|..:..:]] [[..:..:parent_ns:|..:..:parent_ns:]] [[parent_ns:new_page|parent_ns:new_page]] [[parent_ns/new_page|parent_ns/new_page]] [[/start|/start]] EOT; saveWikiText($this->parentBacklinkingId, $text, $summary); $references = array_keys(p_get_metadata($this->parentBacklinkingId, 'relation references', METADATA_RENDER_UNLIMITED)); idx_get_indexer()->addMetaKeys($this->parentBacklinkingId, 'relation_references', $references); $text = <<<EOT [[{$this->movedId}|{$this->movedId}]] [[:{$this->movedId}|:{$this->movedId}]] [[..current_ns:test_page|..current_ns:test_page]] [[..:current_ns:test_page|..:current_ns:test_page]] [[test_page|test_page]] [[.test_page|.test_page]] [[.:test_page|.:test_page]] [[..test_page|..test_page]] [[..:test_page|..:test_page]] [[.:..:test_page|.:..:test_page]] [[new_page|new_page]] [[ftp://somewhere.com|ftp://somewhere.com]] [[http://somewhere.com|http://somewhere.com]] [[start|start]] [[parallel_page|parallel_page]] [[.:|.:]] [[..current_ns:|..current_ns:]] [[..:current_ns:|..:current_ns:]] [[..parallel_ns:|..parallel_ns:]] [[..:parallel_ns:|..:parallel_ns:]] [[..:..:|..:..:]] [[..:..:parent_ns:|..:..:parent_ns:]] [[parent_ns:new_page|parent_ns:new_page]] [[parent_ns/new_page|parent_ns/new_page]] [[/start|/start]] EOT; saveWikiText($this->currentNsBacklinkingId, $text, $summary); $references = array_keys(p_get_metadata($this->currentNsBacklinkingId, 'relation references', METADATA_RENDER_UNLIMITED)); idx_get_indexer()->addMetaKeys($this->currentNsBacklinkingId, 'relation_references', $references); $text = <<<EOT [[{$this->movedId}|{$this->movedId}]] [[:{$this->movedId}|:{$this->movedId}]] [[.current_ns:test_page|.current_ns:test_page]] [[.:current_ns:test_page|.:current_ns:test_page]] [[test_page|test_page]] [[new_page|new_page]] [[ftp://somewhere.com|ftp://somewhere.com]] [[http://somewhere.com|http://somewhere.com]] [[start|start]] [[parallel_page|parallel_page]] [[.:|.:]] [[..current_ns:|..current_ns:]] [[..:current_ns:|..:current_ns:]] [[..parallel_ns:|..parallel_ns:]] [[..:parallel_ns:|..:parallel_ns:]] [[..:..:|..:..:]] [[..:..:parent_ns:|..:..:parent_ns:]] [[parent_ns:new_page|parent_ns:new_page]] [[parent_ns/new_page|parent_ns/new_page]] [[/start|/start]] EOT; saveWikiText($this->otherBacklinkingId, $text, $summary); $references = array_keys(p_get_metadata($this->otherBacklinkingId, 'relation references', METADATA_RENDER_UNLIMITED)); idx_get_indexer()->addMetaKeys($this->otherBacklinkingId, 'relation_references', $references); $text = <<<EOT [[{$this->movedId}|{$this->movedId}]] [[:{$this->movedId}|:{$this->movedId}]] [[..:..current_ns:test_page|..:..current_ns:test_page]] [[..:..:current_ns:test_page|..:..:current_ns:test_page]] [[test_page|test_page]] [[..:test_page|..:test_page]] [[..:test_page|..:test_page]] [[.:..:test_page|.:..:test_page]] [[new_page|new_page]] [[..:new_page|..:new_page]] [[ftp://somewhere.com|ftp://somewhere.com]] [[http://somewhere.com|http://somewhere.com]] [[start|start]] [[parallel_page|parallel_page]] [[.:|.:]] [[..current_ns:|..current_ns:]] [[..:current_ns:|..:current_ns:]] [[..parallel_ns:|..parallel_ns:]] [[..:parallel_ns:|..:parallel_ns:]] [[..:..:|..:..:]] [[..:..:parent_ns:|..:..:parent_ns:]] [[parent_ns:new_page|parent_ns:new_page]] [[parent_ns/new_page|parent_ns/new_page]] [[/start|/start]] EOT; saveWikiText($this->subNsPage, $text, $summary); $references = array_keys(p_get_metadata($this->subNsPage, 'relation references', METADATA_RENDER_UNLIMITED)); idx_get_indexer()->addMetaKeys($this->subNsPage, 'relation_references', $references); parent::setUp(); // we test under useslash conditions $conf['useslash'] = 1; }
/** * Clear all index files */ function _clearindex() { _quietecho("Clearing index... "); idx_get_indexer()->clear(); _quietecho("done.\n"); }
/** * Gets highlight candidates from HTTP_REFERER info * (A compensation for "remove_url_params" option) */ function getCandidatesFromReferer() { global $HIGH; global $ACT; if ($ACT !== 'show' || !empty($HIGH) || !isset($_SERVER['HTTP_REFERER']) || in_array($this->disable_highlight, array('all', 'auto'))) { return; } $referer = (string) $_SERVER['HTTP_REFERER']; if (strpos($referer, DOKU_URL) === 0 && preg_match('/[?&]do=search&id=([^&]+)/', $referer, $matches)) { // users seem to have jumped from search result link in this wiki require_once DOKU_INC . 'inc/fulltext.php'; $query = urldecode($matches[1]); // set highlight candidates // (ft_queryParser has been modified since DokuWiki Rincewind) if (function_exists('idx_get_indexer')) { $Indexer = idx_get_indexer(); $parsed_query = ft_queryParser($Indexer, $query); } else { $parsed_query = ft_queryParser($query); } $HIGH = $parsed_query['highlight']; } }
function search_queries(&$event, $param) { global $ACT; if (is_array($ACT) || $this->is_edit_user) { return; } if ($ACT != 'show' && $ACT != 'search') { return; } //login,admin,profile, revisions,logout if (empty($_SERVER['QUERY_STRING']) || $this->is_excluded($this->ipaddr)) { return; } $queries = unserialize(io_readFile($this->qs_file, false)); if (!$queries) { $queries = array('words' => array(), 'ns' => array(), 'extern' => array()); } $elems = explode('&', html_entity_decode($_SERVER['QUERY_STRING'])); $data_found = false; if (count($elems > 1)) { $words = array(); $temp = array(); foreach ($elems as $el) { if (isset($el) && $el) { list($name, $value) = explode('=', $el); $temp[$name] = $value; } } if (isset($temp['do']) && $temp['do'] == 'search') { $data_found = true; if (function_exists('idx_get_indexer')) { $ar = ft_queryParser(idx_get_indexer(), urldecode($temp['id'])); } else { $ar = ft_queryParser(urldecode($temp['id'])); } if (!empty($ar['phrases']) && !empty($ar['not'])) { $words = array_diff($ar['words'], $ar['not']); } else { $words = $ar['words']; } if (!empty($words)) { foreach ($words as $word) { $this->set_queries($queries, $word, 'words'); } } if (!empty($ar['ns'])) { foreach ($ar['ns'] as $ns) { $this->set_queries($queries, $ns, 'ns'); } } } else { foreach ($this->dw_tokens as $t) { if (isset($temp[$t])) { unset($temp[$t]); } } if (count($temp)) { $keys = array_keys($temp); foreach ($keys as $k) { if (preg_match('/rev\\d*\\[\\d*\\]/', $k)) { unset($temp[$k]); } } if (count($temp)) { $data_found = true; } } foreach ($temp as $name => $val) { $this->set_queries($queries['extern'], urldecode($name), 'name'); if (!$val) { $val = '_empty_'; } $this->set_queries($queries['extern'], urldecode($val), 'val'); $this->set_named_values($queries['extern']['name'][urldecode($name)], urldecode($val)); } } if ($data_found) { io_saveFile($this->qs_file, serialize($queries)); } } }
/** * Looks up pages that will be affected by a move of $src * * Calls addToAffectedPagesList() directly to store the result * * @param string $src source namespace * @param string $dst destination namespace * @param int $class * @param int $type */ protected function findAffectedPages($src, $dst, $class, $type) { $idx = idx_get_indexer(); if ($class == self::CLASS_NS) { $src_ = "{$src}:*"; // use wildcard lookup for namespaces } else { $src_ = $src; } $pages = array(); if ($type == self::TYPE_PAGES) { $pages = $idx->lookupKey('relation_references', $src_); $len = strlen($src); foreach ($pages as &$page) { if (substr($page, 0, $len + 1) === "{$src}:") { $page = $dst . substr($page, $len + 1); } } unset($page); } else { if ($type == self::TYPE_MEDIA) { $pages = $idx->lookupKey('relation_media', $src_); } } $this->addToAffectedPagesList($pages); }
/** * Builds the sorting array: array of arrays (0 = id, 1 = name, 2 = abstract, 3 = ... , etc) * * @param array $ids array of page ids to be sorted * @param array $opt all user options/settings * * @return array $sort_array array of array(one value for each key to be sorted) * $sort_opts sorting options for the msort function * $group_opts grouping options for the mgroup function */ function build_sorting_array($ids, $opt) { global $conf; $sort_array = array(); $sort_opts = array(); $group_opts = array(); $dformat = array(); $wformat = array(); $cnt = 0; // look for 'abc' by title instead of name ('abc' by page-id makes little sense) // title takes precedence over name (should you try to sort by both...why?) $from_title = isset($opt['sort']['title']) ? true : false; // is it necessary to cache the abstract column? $get_abstract = $opt['snippet']['type'] != 'none'; // add any extra columns needed for filtering! $extrakeys = array_diff_key($opt['filter'], $opt['sort']); $col_keys = array_merge($opt['sort'], $extrakeys); // it is more efficient to get all the back-links at once from the indexer metadata if (isset($col_keys['backlinks'])) { $backlinks = idx_get_indexer()->lookupKey('relation_references', $ids); } foreach ($ids as $id) { // getting metadata is very time-consuming, hence ONCE per displayed row $meta = p_get_metadata($id, '', METADATA_DONT_RENDER); if (!isset($meta['date']['created'])) { $meta['date']['created'] = 0; } if (!isset($meta['date']['modified'])) { $meta['date']['modified'] = $meta['date']['created']; } // establish page name (without namespace) $name = noNS($id); // ref to current row, used through out function $row =& $sort_array[$cnt]; // first column is the basic page id $row['id'] = $id; // second column is the display 'name' (used when sorting by 'name') // this also avoids rebuilding the display name when building links later (DRY) $row['name'] = $name; // third column: cache the display name; taken from metadata => 1st heading // used when sorting by 'title' $title = isset($meta['title']) && !empty($meta['title']) ? $meta['title'] : $name; $row['title'] = $title; // needed later in the a, ab ,abc clauses $abc = $from_title ? $title : $name; // fourth column: cache the page abstract if needed; this saves a lot of time later // and avoids repeated slow metadata retrievals (v. slow!) $abstract = $get_abstract ? $meta['description']['abstract'] : ''; $row['abstract'] = $abstract; // fifth column is the displayed text for links; set below $row['display'] = ''; // reset cache of full date for this row $real_date = 0; // ...optional columns foreach ($col_keys as $key => $void) { $value = ''; switch ($key) { case 'a': case 'ab': case 'abc': $value = $this->_first($abc, strlen($key)); break; case 'name': case 'title': // name/title columns already exists by default (col 1,2) // save a few microseconds by just moving on to the next key continue 2; case 'id': $value = $id; break; case 'ns': $value = getNS($id); if (empty($value)) { $value = '[' . $conf['start'] . ']'; } break; case 'creator': $value = $meta['creator']; break; case 'contributor': $value = implode(' ', $meta['contributor']); break; case 'mdate': $value = $meta['date']['modified']; break; case 'cdate': $value = $meta['date']['created']; break; case 'links': $value = $this->_join_keys_if(' ', $meta['relation']['references']); break; case 'backlinks': $value = implode(' ', current($backlinks)); next($backlinks); break; default: // date sorting types (groupable) $dtype = $key[0]; if ($dtype == 'c' || $dtype == 'm') { // we only set real date once per id (needed for grouping) // not per sort column--the date should remain same across all columns // this is always the last column! if ($real_date == 0) { $real_date = $dtype == 'c' ? $meta['date']['created'] : $meta['date']['modified']; $row[self::MGROUP_REALDATE] = $real_date; } // only set date formats once per sort column/key (not per id!), i.e. on first row if ($cnt == 0) { $dformat[$key] = $this->_date_format($key); // collect date in word format for potential use in grouping $wformat[$key] = $opt['spelldate'] ? $this->_date_format_words($dformat[$key]) : ''; } // create a string date used for sorting only // (we cannot just use the real date otherwise it would not group correctly) $value = strftime($dformat[$key], $real_date); } } // set the optional column $row[$key] = $value; } /* provide custom display formatting via string templating {...} */ $matches = array(); $display = $opt['display']; $matched = preg_match_all('/\\{(.+?)\\}/', $display, $matches, PREG_SET_ORDER); // first try to use the custom column names as entered by user if ($matched > 0) { foreach ($matches as $match) { $key = $match[1]; $value = null; if (isset($row[$key])) { $value = $row[$key]; } elseif (isset($meta[$key])) { $value = $meta[$key]; // allow for nested meta keys (e.g. date:created) } elseif (strpos($key, ':') !== false) { $keys = explode(':', $key); if (isset($meta[$keys[0]][$keys[1]])) { $value = $meta[$keys[0]][$keys[1]]; } } elseif ($key == 'mdate') { $value = $meta['date']['modified']; } elseif ($key == 'cdate') { $value = $meta['date']['created']; } if (!is_null($value)) { if (strpos($key, 'date') !== false) { $value = utf8_encode(strftime($opt['dformat'], $value)); } $display = str_replace($match[0], $value, $display); } } // try to match any metadata field; to allow for plain single word display settings // e.g. display=title or display=name } elseif (isset($row[$display])) { $display = $row[$display]; // if all else fails then use the page name (always available) } else { $display = $row['name']; } $row['display'] = $display; $cnt++; } $idx = 0; foreach ($opt['sort'] as $key => $value) { $sort_opts['key'][] = $key; // now the sort direction switch ($value) { case 'a': case 'asc': $dir = self::MSORT_ASC; break; case 'd': case 'desc': $dir = self::MSORT_DESC; break; default: switch ($key) { // sort dates descending by default; text ascending case 'a': case 'ab': case 'abc': case 'name': case 'title': case 'id': case 'ns': case 'creator': case 'contributor': $dir = self::MSORT_ASC; break; default: $dir = self::MSORT_DESC; break; } } $sort_opts['dir'][] = $dir; // set the sort array's data type switch ($key) { case 'mdate': case 'cdate': $type = self::MSORT_NUMERIC; break; default: if ($opt['casesort']) { // case sensitive: a-z then A-Z $type = $opt['natsort'] ? self::MSORT_NAT : self::MSORT_STRING; } else { // case-insensitive $type = $opt['natsort'] ? self::MSORT_NAT_CASE : self::MSORT_STRING_CASE; } } $sort_opts['type'][] = $type; // now establish grouping options switch ($key) { // name strings and full dates cannot be meaningfully grouped (no duplicates!) case 'mdate': case 'cdate': case 'name': case 'title': case 'id': $group_by = self::MGROUP_NONE; break; case 'ns': $group_by = self::MGROUP_NAMESPACE; break; default: $group_by = self::MGROUP_HEADING; } if ($group_by != self::MGROUP_NONE) { $group_opts['key'][$idx] = $key; $group_opts['type'][$idx] = $group_by; $group_opts['dformat'][$idx] = $wformat[$key]; $idx++; } } return array($sort_array, $sort_opts, $group_opts); }
/** * Use this tool to reindex your wiki * * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html * @author Abilio Marques <https://github.com/abiliojr> */ if (!defined('DOKU_ROOT')) { define('DOKU_ROOT', realpath(dirname(__FILE__) . '/../../../') . '/'); } define('NOSESSION', 1); require_once DOKU_ROOT . 'inc/init.php'; global $conf; $sphinx = new SphinxSearch(); // clear the index idx_get_indexer()->clear(); // must complete the basic indexing first search($data, $conf['datadir'], 'search_allpages', array('skipacl' => true)); foreach ($data as $val) { idx_addPage($val['id'], false, true); } // only now the backlinks counters in the dokuwiki index are valid // so lets update sphinxsearch to reflect them $pages = idx_get_indexer()->getPages(); foreach ($pages as $page) { $namespace = getNS($page); if (!$namespace) { $namespace = 'root'; } $title = str_replace($conf['sepchar'], ' ', noNS($page)); $sphinx->updateReferences($namespace, $title, count(ft_backlinks($page, true))); }