1<?php 2/** 3 * Script to search in dokuwiki documents 4 * 5 * @author Yaroslav Vorozhko <yaroslav@ivinco.com> 6 */ 7 8if(!defined('DOKU_INC')) die(); 9if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 10 11require_once(DOKU_INC.'inc/parser/parser.php'); 12 13require_once(DOKU_PLUGIN . 'action.php'); 14require_once(DOKU_PLUGIN . 'sphinxsearch/sphinxapi.php'); 15require_once(DOKU_PLUGIN . 'sphinxsearch/PageMapper.php'); 16require_once(DOKU_PLUGIN . 'sphinxsearch/SphinxSearch.php'); 17require_once(DOKU_PLUGIN . 'sphinxsearch/functions.php'); 18 19 20class action_plugin_sphinxsearch extends DokuWiki_Action_Plugin { 21 var $_search = null; 22 23 /** 24 * return some info 25 */ 26 function getInfo() { 27 return confToHash(dirname(__FILE__).'/plugin.info.txt'); 28 } 29 30 /** 31 * Register to the content display event to place the results under it. 32 */ 33 /** 34 * register the eventhandlers 35 */ 36 function register(&$controller){ 37 $controller->register_hook('TPL_CONTENT_DISPLAY', 'BEFORE', $this, 'handle_act_unknown', array()); 38 } 39 40 /** 41 * If our own 'googlesearch' action was given we produce our content here 42 */ 43 function handle_act_unknown(&$event, $param){ 44 global $ACT; 45 global $QUERY; 46 if($ACT != 'search') return; // nothing to do for us 47 48 // we can handle it -> prevent others 49 $event->stopPropagation(); 50 $event->preventDefault(); 51 52 53 $this->_search($QUERY,$_REQUEST['start'],$_REQUEST['prev']); 54 } 55 56 /** 57 * do the search and displays the result 58 */ 59 function _search($query, $start, $prev) { 60 global $conf; 61 62 $start = (int) $start; 63 if($start < 0) $start = 0; 64 65 $categories = $this->_getCategories($query); 66 $keywords = $this->_getKeywords($query); 67 68 $search = new SphinxSearch($this->getConf('host'), $this->getConf('port'), $this->getConf('index')); 69 $search->setSnippetSize($this->getConf('snippetsize')); 70 $search->setArroundWordsCount($this->getConf('aroundwords')); 71 $search->setTitlePriority($this->getConf('title_priority')); 72 $search->setBodyPriority($this->getConf('body_priority')); 73 $search->setCategoriesPriority($this->getConf('categories_priority')); 74 75 $pagesList = $search->search($keywords, $categories, $start, $this->getConf('maxresults')); 76 $this->_search = $search; 77 78 if ($search->getError()){ 79 echo '<b>' . $search->getError() . '</b>!'; 80 return; 81 } 82 83 $totalFound = $search->getTotalFound(); 84 if(empty($pagesList)){ 85 echo '<b>Nothing was found by ' . $query . '</b>!'; 86 return; 87 } else { 88 echo '<style type="text/css"> 89 div.dokuwiki .search_snippet{ 90 color:#000000; 91 margin-left:0px; 92 font-size: 13px; 93 } 94 div.dokuwiki .search_result{ 95 width:800px; 96 float:left; 97 } 98 div.dokuwiki .search_sidebar{ 99 width:200px; 100 float:right; 101 margin-right: 30px; 102 } 103 div.dokuwiki .search_result_row{ 104 color:#000000; 105 margin-left:0px; 106 width:800px; 107 } 108 div.dokuwiki .search_result_row_child{ 109 color:#000000; 110 margin-left:30px; 111 width:800px; 112 } 113 div.dokuwiki .search_cnt{ 114 color:#CCCCCC; 115 font-size: 10px; 116 } 117 div.dokuwiki .search_nmsp{ 118 font-size: 10px; 119 } 120 div.dokuwiki .sphinxsearch_nav{ 121 clear:both; 122 } 123 </style> 124 '; 125 126 echo '<h2>Found '.$totalFound . ($totalFound == 1 ? ' document ' : ' documents ') . ' for query "' . hsc($query).'"</h2>'; 127 echo '<div class="search_result">'; 128 // printout the results 129 $pageListGroupByPage = array(); 130 foreach ($pagesList as $row) { 131 $page = $row['page']; 132 if(!isset ($pageListGroupByPage[$page])){ 133 $pageListGroupByPage[$page] = $row; 134 } else { 135 $pageListGroupByPage[$page]['subpages'][] = $row; 136 } 137 } 138 foreach ($pageListGroupByPage as $row) { 139 $this->_showResult($row); 140 if(!empty($row['subpages'])){ 141 foreach($row['subpages'] as $sub){ 142 $this->_showSubResult($sub); 143 } 144 } 145 146 } 147 echo '</div>'; 148 echo '<div class="search_sidebar">'; 149 printNamespaces($keywords); 150 echo '</div>'; 151 echo '<div class="sphinxsearch_nav">'; 152 if ($start > 1){ 153 //$prev = $start - $this->getConf('maxresults'); 154 //if($prev < 0) $prev = 0; 155 if(false !== strpos($prev, ',')){ 156 $prevAr = explode(",", $prev); 157 $prevNum = $prevAr[count($prevAr)-1]; 158 unset($prevAr[count($prevAr)-1]); 159 $prevPrev = implode(",", $prevAr); 160 } else { 161 $prevNum = 0; 162 } 163 164 echo $this->external_link(wl('',array('do'=>'search','id'=>$query,'start'=>$prevNum, 'prev'=>$prevPrev),'false','&'), 165 'prev','wikilink1 gs_prev',$conf['target']['interwiki']); 166 } 167 echo ' '; 168 169 //if($start + $this->getConf('maxresults') < $totalFound){ 170 //$next = $start + $this->getConf('maxresults'); 171 if($start + $search->getOffset()< $totalFound){ 172 $next = $start + $search->getOffset(); 173 $prev = $prev.','.$start; 174 echo $this->external_link(wl('',array('do'=>'search','id'=>$query,'start'=>$next,'prev'=>$prev),'false','&'), 175 'next','wikilink1 gs_next',$conf['target']['interwiki']); 176 } 177 echo '</div>'; 178 } 179 180 } 181 182 function _showResult($row) 183 { 184 $page = $row['page']; 185 $bodyExcerpt = $row['bodyExcerpt']; 186 $titleTextExcerpt = $row['titleTextExcerpt']; 187 $hid = $row['hid']; 188 189 $metaData = p_get_metadata($page); 190 191 if (!empty($titleTextExcerpt)){ 192 $titleText = $titleTextExcerpt; 193 } elseif(!empty($row['title_text'])){ 194 $titleText = $row['title_text']; 195 } elseif(!empty($metaData['title'])){ 196 $titleText = hsc($metaData['title']); 197 } else { 198 $titleText = hsc($page); 199 } 200 201 $namespaces = getNsLinks($page, $keywords, $this->_search); 202 $href = !empty($hid) ? (wl($page).'#'.$hid) : wl($page); 203 204 echo '<div class="search_result_row">'; 205 206 echo '<a href="'.$href.'" title="" class="wikilink1">'.$titleText.'</a><br/>'; 207 echo '<div class="search_snippet">'; 208 echo strip_tags($bodyExcerpt, '<b>,<strong>'); 209 echo '</div>'; 210 $sep=':'; 211 $i = 0; 212 echo '<span class="search_nmsp">'; 213 foreach ($namespaces as $name){ 214 $link = $name['link']; 215 $pageTitle = $name['title']; 216 tpl_link($link, $pageTitle); 217 if ($i++ < count($namespaces)-1){ 218 echo $sep; 219 } 220 } 221 if (!empty($hid)){ 222 echo '#'.$hid; 223 } 224 echo '</span>'; 225 echo '<span class="search_cnt"> - Last modified '.date("Y-m-d H:i",$metaData['date']['modified']).'</span> '; 226 echo '<span class="search_cnt">by '.$metaData['last_change']['user'].'</span> '; 227 echo '<br />'; 228 echo '<br />'; 229 echo '</div>'; 230 } 231 232 function _showSubResult($row) 233 { 234 $page = $row['page']; 235 $bodyExcerpt = $row['bodyExcerpt']; 236 $titleTextExcerpt = $row['titleTextExcerpt']; 237 $hid = $row['hid']; 238 239 $metaData = p_get_metadata($page); 240 241 if (!empty($titleTextExcerpt)){ 242 $titleText = $titleTextExcerpt; 243 } elseif(!empty($row['title_text'])){ 244 $titleText = $row['title_text']; 245 } elseif(!empty($metaData['title'])){ 246 $titleText = hsc($metaData['title']); 247 } else { 248 $titleText = hsc($page); 249 } 250 251 $namespaces = getNsLinks($page, $keywords, $this->_search); 252 $href = !empty($hid) ? (wl($page).'#'.$hid) : wl($page); 253 254 echo '<div class="search_result_row_child">'; 255 256 echo '<a href="'.$href.'" title="" class="wikilink1">'.$titleText.'</a><br/>'; 257 echo '<div class="search_snippet">'; 258 echo strip_tags($bodyExcerpt, '<b>,<strong>'); 259 echo '</div>'; 260 $sep=':'; 261 $i = 0; 262 echo '<span class="search_nmsp">'; 263 foreach ($namespaces as $name){ 264 $link = $name['link']; 265 $pageTitle = $name['title']; 266 tpl_link($link, $pageTitle); 267 if ($i++ < count($namespaces)-1){ 268 echo $sep; 269 } 270 } 271 if (!empty($hid)){ 272 echo '#'.$hid; 273 } 274 echo '</span>'; 275 echo '<span class="search_cnt"> - Last modified '.date("Y-m-d H:i",$metaData['date']['modified']).'</span> '; 276 echo '<span class="search_cnt">by '.$metaData['last_change']['user'].'</span> '; 277 echo '<br />'; 278 echo '<br />'; 279 echo '</div>'; 280 } 281 282 function searchform(){ 283 global $lang; 284 global $ACT; 285 global $QUERY; 286 287 // don't print the search form if search action has been disabled 288 if (!actionOk('search')) return false; 289 290 print '<form action="'.wl().'" accept-charset="utf-8" class="search" id="dw__search"><div class="no">'; 291 print '<input type="hidden" name="do" value="search" />'; 292 print '<input type="text" '; 293 if($ACT == 'search') print 'value="'.htmlspecialchars($QUERY).'" '; 294 print 'id="qsearch__in" accesskey="f" name="id" class="edit" title="[ALT+F]" />'; 295 print '<input type="submit" value="'.$lang['btn_search'].'" class="button" title="'.$lang['btn_search'].'" />'; 296 print '</div></form>'; 297 return true; 298 } 299 300 function _getCategories($query) 301 { 302 $categories = ''; 303 $query = urldecode($query); 304 if (false !== ($pos = strpos($query, "@categories"))){; 305 $categories = substr($query, $pos + strlen("@categories")); 306 } 307 return trim($categories); 308 } 309 310 function _getKeywords($query) 311 { 312 $keywords = $query; 313 $query = urldecode($query); 314 if (false !== ($pos = strpos($query, "@categories"))){; 315 $keywords = substr($keywords, 0, $pos); 316 } 317 return trim($keywords); 318 } 319} 320 321?> 322