Wiki source code of Lucene Search
Show last authors
author | version | line-number | content |
---|---|---|---|
1 | {{velocity}} | ||
2 | $xwiki.ssfx.use("uicomponents/search/search.css", true)## | ||
3 | ## Disable the document extra data: comments, attachments, history... | ||
4 | #set($docextras = []) | ||
5 | ## =================== | ||
6 | ## Lucene search | ||
7 | ## =================== | ||
8 | ## Inputs : $request.text | ||
9 | ## Outputs : $list, $isScored | ||
10 | ## =================== | ||
11 | ## Uncomment this line to overload the maximum list of wiki where to search (also the one listed in the wikis combobox) | ||
12 | ## #set($allwikinamelist = ["xwiki", "wiki1", "wiki2"]) | ||
13 | ## | ||
14 | ## Uncomment this line to overload the wikis where to search | ||
15 | ## #set($wikinames = "xwiki,wiki,wiki") | ||
16 | ## | ||
17 | ## Uncomment this line to overload the languages to search | ||
18 | ## #set($languages = "default,en,de") | ||
19 | #set ($rssmode = ("$!request.xpage" == 'plain')) | ||
20 | #if ($rssmode) | ||
21 | $response.setContentType('application/rss+xml') | ||
22 | #end | ||
23 | ## -------------------------- | ||
24 | ## Hidden documents filtering | ||
25 | ## -------------------------- | ||
26 | #set($hiddenClause = ' +hidden:false') | ||
27 | ## TODO: rewrite this when we'll have a user configuration script service | ||
28 | #if($xwiki.getDocument($xcontext.user).getValue('displayHiddenDocuments') == 1) | ||
29 | #set($hiddenClause = '') | ||
30 | #end | ||
31 | ## --------------- | ||
32 | ## Space filtering | ||
33 | ## --------------- | ||
34 | #set($extraClause = '') | ||
35 | #set($spaces = $xwiki.spaces) | ||
36 | #set($selectedSpace = "$!request.space") | ||
37 | #if($selectedSpace != '' && !$blacklistedSpaces.contains($selectedSpace)) | ||
38 | #set($extraClause = " +exactspace:""${selectedSpace}""") | ||
39 | #end | ||
40 | ## ---------------------------------------------------------------------- | ||
41 | ## Exclude Blacklisted spaces ($blacklistedSpaces is set in xwikivars.vm) | ||
42 | ## Also exclude WebPreferences. | ||
43 | ## ---------------------------------------------------------------------- | ||
44 | #foreach ($blacklistedSpace in $blacklistedSpaces) | ||
45 | #set ($extraClause = " -exactspace:${blacklistedSpace}${extraClause}") | ||
46 | #end | ||
47 | #if(!$hasAdmin && !$isAdvancedUser) | ||
48 | #set ($extraClause = " -name:WebPreferences${extraClause}") | ||
49 | #end | ||
50 | ## --------------- | ||
51 | ## Space macros | ||
52 | ## --------------- | ||
53 | #macro(spaceoption $space $selectedSpace) | ||
54 | <option value="${space}" #if($selectedSpace == $space)selected="selected"#end>$space</option> | ||
55 | #end | ||
56 | #macro(spaceselect $selectedSpace $spaces) | ||
57 | <select name="space" title="$services.localization.render('search.page.bar.spaces.title')"> | ||
58 | <option value="" #if($selectedSpace == '')selected="selected"#end>$services.localization.render('search.page.bar.spaces.all')</option> | ||
59 | #foreach($space in $spaces) | ||
60 | #if (!$blacklistedSpaces.contains($space) && $xwiki.hasAccessLevel('view', "${space}.DocumentReservedForInternalXWikiUsage${mathtool.random(0, 999)}")) | ||
61 | #spaceoption($space $selectedSpace) | ||
62 | #end | ||
63 | #end | ||
64 | </select> | ||
65 | #end | ||
66 | ## --------------- | ||
67 | ## Wikis filtering | ||
68 | ## --------------- | ||
69 | ## Parse provided wikis | ||
70 | #set($wikinamelist = []) | ||
71 | #if (!$wikinames) | ||
72 | #set($wikinametable = $request.getParameterValues("wikinames")) | ||
73 | #if (!$wikinametable || $request.wikinames == "") | ||
74 | #set($wikinametable = $allwikinamelist) | ||
75 | #end | ||
76 | #set($wikinames = '') | ||
77 | #foreach($wikiname in $wikinametable) | ||
78 | #set($ok = $wikinamelist.add($wikiname)) | ||
79 | #if($wikinames != "") | ||
80 | #set($wikinames = $wikinames + ",") | ||
81 | #end | ||
82 | #set($wikinames = $wikinames + $wikiname) | ||
83 | #end | ||
84 | #if (!$xcontext.isMainWiki() && $wikinames == '') | ||
85 | #set($wikinames = $xcontext.database) | ||
86 | #end | ||
87 | #else | ||
88 | #set($wikinametable = $wikinames.split(", ")) | ||
89 | #foreach($wikiname in $wikinametable) | ||
90 | #set($ok = $wikinamelist.add($wikiname)) | ||
91 | #end | ||
92 | #end | ||
93 | ## | ||
94 | #if($xcontext.isMainWiki()) | ||
95 | #if(!$allwikinamelist) | ||
96 | #set($currentwikiname = $xcontext.database) | ||
97 | #set($allwikinamelist = $xwiki.wikiNames) | ||
98 | #end | ||
99 | ## --------------- | ||
100 | ## Wikis macros | ||
101 | ## --------------- | ||
102 | #macro(wikioption $wikiname $wikinamelist) | ||
103 | <option value="$wikiname" #if($wikinamelist.contains($wikiname))selected="selected"#end>$wikiname</option> | ||
104 | #end | ||
105 | #macro(wikisselect $wikinamelist $allwikinamelist) | ||
106 | ## TODO: find a scaling way to handle wikis multiselect, does not use multiple="multiple" for now because it does not looks nice | ||
107 | <select name="wikinames"> | ||
108 | <option value="" selected="selected">$services.localization.render('search.page.bar.wikis.all')</option> | ||
109 | #foreach($wikiname in $allwikinamelist) | ||
110 | #wikioption($wikiname $wikinamelist) | ||
111 | #end | ||
112 | </select> | ||
113 | #end | ||
114 | #else | ||
115 | #if($wikinames == '') | ||
116 | #set($wikinames = $xcontext.mainWikiName) | ||
117 | #end | ||
118 | #end | ||
119 | ## --------------- | ||
120 | ## Query preparation | ||
121 | ## --------------- | ||
122 | #set($text = "$!request.getParameter('text')") | ||
123 | #set($query = $text) | ||
124 | #set($utext = $escapetool.url($query)) | ||
125 | #set($defaultItemsPerPage = 30) | ||
126 | #set($itemsPerPage = $mathtool.toInteger("$!{request.perPage}")) | ||
127 | #if(!$itemsPerPage || $itemsPerPage <= 0) | ||
128 | #set($itemsPerPage = $defaultItemsPerPage) | ||
129 | #end | ||
130 | ## --------------- | ||
131 | ## Query form | ||
132 | ## --------------- | ||
133 | #if(!$rssmode) | ||
134 | {{html}} | ||
135 | <form action="" id="searchBar"> | ||
136 | <div class="centered"> | ||
137 | <label for="text" class="hidden">$services.localization.render('search.page.query.label')</label> | ||
138 | <input type="text" id="text" name="text" class="searchQuery #if($text == '') withTip#end" #if($text == '') value="$services.localization.render('search.page.bar.query.tip')" #else value="${escapetool.xml($text)}" #end title="$services.localization.render('search.page.bar.query.title')"/> | ||
139 | #if ($xcontext.isMainWiki()) | ||
140 | #wikisselect($request.wikinames $allwikinamelist) | ||
141 | #end | ||
142 | #spaceselect($selectedSpace $spaces) | ||
143 | <span class='buttonwrapper'> | ||
144 | <input type="submit" class="button searchButton" value="$services.localization.render('search.page.bar.submit')" title="$services.localization.render('search.page.bar.submit.title')"/> | ||
145 | </span> | ||
146 | <div class="searchHelp">$services.localization.render('search.page.bar.querytip')</div> | ||
147 | </div> | ||
148 | </form> | ||
149 | {{/html}} | ||
150 | #end | ||
151 | ## --------------- | ||
152 | ## Results processing | ||
153 | ## --------------- | ||
154 | ## Since Lucene doesn't support '*' or '?' as the first character we just remove it for now. Note that the SOLR | ||
155 | ## search doesn't have this limitation | ||
156 | #set ($query = $stringtool.removeStart($query, '*')) | ||
157 | #set ($query = $stringtool.removeStart($query, '?')) | ||
158 | ## '!' is also an operator, and if it's not at the start of a word, it will cause a query parsing exception | ||
159 | #set ($query = $query.replaceAll('(?<!^| )!++|!++(?=$| )', '')) | ||
160 | #if($query != '') | ||
161 | #set($lucene = $xwiki.getPlugin("lucene")) | ||
162 | #if($lucene) | ||
163 | ## --------------- | ||
164 | ## Lucene search | ||
165 | ## --------------- | ||
166 | #set($searchresults = $lucene.getSearchResults("+(${query})${extraClause}${hiddenClause}", '', $wikinames, $!languages)) | ||
167 | #if($searchresults && $searchresults.getHitcount() > 0) | ||
168 | ## ----------------- | ||
169 | ## Pagination (top) | ||
170 | ## ----------------- | ||
171 | #if(!$rssmode) | ||
172 | #set($paginationParameters = {'url' : $doc.getURL('view', "text=${escapetool.url($query)}&space=${escapetool.url($selectedSpace)}"), 'totalItems' : $searchresults.getHitcount(), 'defaultItemsPerPage' : $defaultItemsPerPage, 'position': 'top'}) | ||
173 | |||
174 | {{html}} | ||
175 | #pagination($paginationParameters) | ||
176 | {{/html}} | ||
177 | #end | ||
178 | ## ----------------- | ||
179 | ## Display results | ||
180 | ## ----------------- | ||
181 | #set($firstIndex = "$!{paginationParameters.firstItem}") | ||
182 | #if($firstIndex == '') | ||
183 | #set($firstIndex = "$!request.getParameter('firstIndex')") | ||
184 | #if($firstIndex == '') | ||
185 | #set($firstIndex = '0') | ||
186 | #end | ||
187 | #end | ||
188 | #set($firstIndex = $mathtool.toInteger($firstIndex)) | ||
189 | #set($firstIndex = $firstIndex + 1) | ||
190 | #set($results = $searchresults.getResults("$firstIndex", "$itemsPerPage")) | ||
191 | #if ($rssmode) | ||
192 | #set ($list = []) | ||
193 | #foreach ($item in $results) | ||
194 | #if ($item.type != "attachment") | ||
195 | #set ($ok = $list.add(0, "${item.space}.${item.name}")) | ||
196 | #end | ||
197 | #end | ||
198 | #set ($feed = $xwiki.feed.getDocumentFeed($list, {})) | ||
199 | #set ($feedURI = $doc.getExternalURL("view")) | ||
200 | #set ($discard = $feed.setLink($feedURI)) | ||
201 | #set ($discard = $feed.setUri($feedURI)) | ||
202 | #set ($discard = $feed.setAuthor('XWiki')) | ||
203 | #set ($discard = $feed.setTitle($services.localization.render('search.rss', [$text]))) | ||
204 | #set ($discard = $feed.setDescription($services.localization.render('search.rss', [$text]))) | ||
205 | #set ($discard = $feed.setLanguage($xcontext.language)) | ||
206 | #set ($discard = $feed.setCopyright($xwiki.getXWikiPreference('copyright'))) | ||
207 | {{{$xwiki.feed.getFeedOutput($feed, 'rss_2.0')}}} | ||
208 | #else | ||
209 | #set ($list = $results) | ||
210 | #set ($isScored = true) | ||
211 | |||
212 | {{include reference="XWiki.Results"/}} | ||
213 | #end | ||
214 | ## ----------------- | ||
215 | ## Pagination (bottom) | ||
216 | ## ----------------- | ||
217 | #if(!$rssmode) | ||
218 | #set($paginationParameters.position = 'bottom') | ||
219 | |||
220 | {{html}} | ||
221 | #pagination($paginationParameters) | ||
222 | {{/html}} | ||
223 | ## --------------- | ||
224 | ## RSS link | ||
225 | ## --------------- | ||
226 | #if($selectedSpace == '') | ||
227 | #set($rssURL = $xwiki.getURL($doc.fullName, 'get', "xpage=plain&outputSyntax=plain&text=${utext}" )) | ||
228 | #else | ||
229 | #set($rssURL = $xwiki.getURL($doc.fullName, 'get', "xpage=plain&outputSyntax=plain&space=${selectedSpace}&text=${utext}")) | ||
230 | #end | ||
231 | |||
232 | {{html}} | ||
233 | <a href="${rssURL}" class='hasIcon iconRSS'>$services.localization.render('search.rss', ["[$escapetool.xml($query)]"])</a> | ||
234 | {{/html}} | ||
235 | #end | ||
236 | #else | ||
237 | |||
238 | {{info}}$services.localization.render('search.page.results.noResults'){{/info}} | ||
239 | #end | ||
240 | #else | ||
241 | |||
242 | {{error}}$services.localization.render('search.lucene.plugin.notfound'){{/error}} | ||
243 | #end | ||
244 | #end | ||
245 | #if (!$rssmode) | ||
246 | ## --------------- | ||
247 | ## Rebuild processing | ||
248 | ## --------------- | ||
249 | #set($lucene = $xwiki.getPlugin("lucene")) | ||
250 | #if($lucene) | ||
251 | ## --------------- | ||
252 | ## Queue | ||
253 | ## --------------- | ||
254 | #set ($queuesize = $xwiki.lucene.getQueueSize()) | ||
255 | #if ($queuesize > 0) | ||
256 | |||
257 | {{info}}$services.localization.render('search.page.lucene.rebuilding', [${queuesize}]){{/info}} | ||
258 | #end | ||
259 | #end## lucene exists | ||
260 | #end## !$rssmode | ||
261 | {{/velocity}} |