0 Votes

Wiki source code of Lucene Search

Last modified by Ryan C on 2025/03/07 23:52

Show last authors
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)}&amp;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}}