Attachment 'fullsearch_new.py'

Download

   1 # -*- coding: iso-8859-1 -*-
   2 """
   3     MoinMoin - fullsearch action
   4 
   5     This is the backend of the search form. Search pages and print results.
   6 
   7     @copyright: 2001 by Juergen Hermann <jh@web.de>
   8     @license: GNU GPL, see COPYING for details.
   9 
  10     Comments about my changes (MarcelHäfner / 24.06.2009):
  11     I wanted a search witch finds/displays only wiki pages (primary no attachments)
  12     For this I changed this action; so you can now add to our theme / html searchform 
  13     a hidden paramter like this:
  14     <input id="searchmimetype" type="hidden" value="text/wiki" name="mimetype"/> 
  15 
  16     for more details, please see on MoinMoin this page: FullSearchMimeTypeSupport
  17 
  18 """
  19 
  20 import re, time
  21 from MoinMoin.Page import Page
  22 from MoinMoin import wikiutil
  23 from MoinMoin.support.parsedatetime.parsedatetime import Calendar
  24 
  25 def checkTitleSearch(request):
  26     """ Return 1 for title search, 0 for full text search, -1 for idiot spammer
  27         who tries to press all buttons at once.
  28 
  29     When used in FullSearch macro, we have 'titlesearch' parameter with
  30     '0' or '1'. In standard search, we have either 'titlesearch' or
  31     'fullsearch' with localized string. If both missing, default to
  32     True (might happen with Safari) if this isn't an advanced search.
  33 """
  34     form = request.form
  35     if 'titlesearch' in form and 'fullsearch' in form:
  36         ret = -1 # spammer / bot
  37     else:
  38         try:
  39             ret = int(form['titlesearch'][0])
  40         except ValueError:
  41             ret = 1
  42         except KeyError:
  43             ret = ('fullsearch' not in form and not isAdvancedSearch(request)) and 1 or 0
  44     return ret
  45 
  46 def isAdvancedSearch(request):
  47     """ Return True if advanced search is requested """
  48     try:
  49         return int(request.form['advancedsearch'][0])
  50     except KeyError:
  51         return False
  52 
  53 
  54 def searchHints(f, hints):
  55     """ Return a paragraph showing hints for a search
  56 
  57     @param f: the formatter to use
  58     @param hints: list of hints (as strings) to show
  59     """
  60     return ''.join([
  61         f.paragraph(1, attr={'class': 'searchhint'}),
  62         # this is illegal formatter usage anyway, so we can directly use a literal
  63         "<br>".join(hints),
  64         f.paragraph(0),
  65     ])
  66 
  67 
  68 def execute(pagename, request, fieldname='value', titlesearch=0, statistic=0):
  69     _ = request.getText
  70     titlesearch = checkTitleSearch(request)
  71     if titlesearch < 0:
  72         request.makeForbidden403()
  73         request.surge_protect(kick_him=True) # get rid of spammer
  74         return
  75 
  76     advancedsearch = isAdvancedSearch(request)
  77 
  78     # context is relevant only for full search
  79     if titlesearch:
  80         context = 0
  81     elif advancedsearch:
  82         context = 180 # XXX: hardcoded context count for advancedsearch
  83     else:
  84         context = int(request.form.get('context', [0])[0])
  85 
  86     # Get other form parameters
  87     needle = request.form.get(fieldname, [''])[0]
  88     case = int(request.form.get('case', [0])[0])
  89     regex = int(request.form.get('regex', [0])[0]) # no interface currently
  90     hitsFrom = int(request.form.get('from', [0])[0])
  91     mtime = None
  92     msg = ''
  93     historysearch = 0
  94     mimetype = request.form.get('mimetype', [0]) #moved up; from only used in advanced search 
  95 
  96     # if advanced search is enabled we construct our own search query
  97     if advancedsearch:
  98         and_terms = request.form.get('and_terms', [''])[0].strip()
  99         or_terms = request.form.get('or_terms', [''])[0].strip()
 100         not_terms = request.form.get('not_terms', [''])[0].strip()
 101         #xor_terms = request.form.get('xor_terms', [''])[0].strip()
 102         categories = request.form.get('categories', [''])
 103         timeframe = request.form.get('time', [''])[0].strip()
 104         language = request.form.get('language', [''])
 105         excludeunderlay = request.form.get('excludeunderlay', [0])[0]
 106         nosystemitems = request.form.get('nosystemitems', [0])[0]
 107         historysearch = request.form.get('historysearch', [0])[0]
 108 
 109         mtime = request.form.get('mtime', [''])[0]
 110         if mtime:
 111             mtime_parsed = None
 112 
 113             # get mtime from known date/time formats
 114             for fmt in (request.user.datetime_fmt,
 115                     request.cfg.datetime_fmt, request.user.date_fmt,
 116                     request.cfg.date_fmt):
 117                 try:
 118                     mtime_parsed = time.strptime(mtime, fmt)
 119                 except ValueError:
 120                     continue
 121                 else:
 122                     break
 123 
 124             if mtime_parsed:
 125                 mtime = time.mktime(mtime_parsed)
 126             else:
 127                 # didn't work, let's try parsedatetime
 128                 cal = Calendar()
 129                 mtime_parsed, invalid_flag = cal.parse(mtime)
 130                 # XXX it is unclear if usage of localtime here and in parsedatetime module is correct.
 131                 # time.localtime is the SERVER's local time and of no relevance to the user (being
 132                 # somewhere in the world)
 133                 # mktime is reverse function for localtime, so this maybe fixes it again!?
 134                 if not invalid_flag and mtime_parsed <= time.localtime():
 135                     mtime = time.mktime(mtime_parsed)
 136                 else:
 137                     mtime_parsed = None # we don't use invalid stuff
 138 
 139             # show info
 140             if mtime_parsed:
 141                 # XXX mtime_msg is not shown in some cases
 142                 mtime_msg = _("(!) Only pages changed since '''%s''' are being displayed!",
 143                               wiki=True) % request.user.getFormattedDateTime(mtime)
 144             else:
 145                 mtime_msg = _('/!\\ The modification date you entered was not '
 146                         'recognized and is therefore not considered for the '
 147                         'search results!', wiki=True)
 148         else:
 149             mtime_msg = None
 150 
 151         word_re = re.compile(r'(\"[\w\s]+"|\w+)')
 152         needle = ''
 153         if categories[0]:
 154             needle += 'category:%s ' % ','.join(categories)
 155         if language[0]:
 156             needle += 'language:%s ' % ','.join(language)
 157         if mimetype[0]:
 158             needle += 'mimetype:%s ' % ','.join(mimetype)
 159         if excludeunderlay:
 160             needle += '-domain:underlay '
 161         if nosystemitems:
 162             needle += '-domain:system '
 163         if and_terms:
 164             needle += '(%s) ' % and_terms
 165         if not_terms:
 166             needle += '(%s) ' % ' '.join(['-%s' % t for t in word_re.findall(not_terms)])
 167         if or_terms:
 168             needle += '(%s) ' % ' or '.join(word_re.findall(or_terms))
 169     else:
 170         #added for mimetype search over the searchform
 171         if mimetype[0]:
 172             needle = 'mimetype:%s (%s)' % (','.join(mimetype), needle)
 173            
 174 
 175     # check for sensible search term
 176     stripped = needle.strip()
 177     if len(stripped) == 0:
 178         request.theme.add_msg(_('Please use a more selective search term instead '
 179                 'of {{{"%s"}}}', wiki=True) % wikiutil.escape(needle), "error")
 180         Page(request, pagename).send_page()
 181         return
 182     needle = stripped
 183 
 184     # Setup for type of search
 185     if titlesearch:
 186         title = _('Title Search: "%s"')
 187         sort = 'page_name'
 188     else:
 189         if advancedsearch:
 190             title = _('Advanced Search: "%s"')
 191         else:
 192             title = _('Full Text Search: "%s"')
 193         sort = 'weight'
 194 
 195     # search the pages
 196     from MoinMoin.search import searchPages, QueryParser, QueryError
 197     try:
 198         query = QueryParser(case=case, regex=regex,
 199                 titlesearch=titlesearch).parse_query(needle)
 200     except QueryError: # catch errors in the search query
 201         request.theme.add_msg(_('Your search query {{{"%s"}}} is invalid. Please refer to '
 202                 'HelpOnSearching for more information.', wiki=True, percent=True) % wikiutil.escape(needle), "error")
 203         Page(request, pagename).send_page()
 204         return
 205 
 206     results = searchPages(request, query, sort, mtime, historysearch)
 207 
 208     # directly show a single hit for title searches
 209     # this is the "quick jump" functionality if you don't remember
 210     # the pagename exactly, but just some parts of it
 211     if titlesearch and len(results.hits) == 1:
 212         page = results.hits[0]
 213         if not page.attachment: # we did not find an attachment
 214             page = Page(request, page.page_name)
 215             highlight = query.highlight_re()
 216             if highlight:
 217                 querydict = {'highlight': highlight}
 218             else:
 219                 querydict = {}
 220             url = page.url(request, querystr=querydict)
 221             request.http_redirect(url)
 222             return
 223     if not results.hits: # no hits?
 224         f = request.formatter
 225         querydict = wikiutil.parseQueryString(request.query_string)
 226         querydict.update({'titlesearch': 0})
 227 
 228         request.theme.add_msg(_('Your search query {{{"%s"}}} didn\'t return any results. '
 229                 'Please change some terms and refer to HelpOnSearching for '
 230                 'more information.%s', wiki=True, percent=True) % (wikiutil.escape(needle),
 231                     titlesearch and ''.join([
 232                         '<br>',
 233                         _('(!) Consider performing a', wiki=True), ' ',
 234                         f.url(1, href=request.page.url(request, querydict, escape=0)),
 235                         _('full-text search with your search terms'),
 236                         f.url(0), '.',
 237                     ]) or ''), "error")
 238         Page(request, pagename).send_page()
 239         return
 240 
 241     request.emit_http_headers()
 242 
 243     # This action generates data using the user language
 244     request.setContentLanguage(request.lang)
 245 
 246     request.theme.send_title(title % needle, form=request.form, pagename=pagename)
 247 
 248     # Start content (important for RTL support)
 249     request.write(request.formatter.startContent("content"))
 250 
 251     # Hints
 252     f = request.formatter
 253     hints = []
 254 
 255     if titlesearch:
 256         querydict = wikiutil.parseQueryString(request.query_string)
 257         querydict.update({'titlesearch': 0})
 258 
 259         hints.append(''.join([
 260             _("(!) You're performing a title search that might not include"
 261                 ' all related results of your search query in this wiki. <<BR>>', wiki=True),
 262             ' ',
 263             f.url(1, href=request.page.url(request, querydict, escape=0)),
 264             f.text(_('Click here to perform a full-text search with your '
 265                 'search terms!')),
 266             f.url(0),
 267         ]))
 268 
 269     if advancedsearch and mtime_msg:
 270         hints.append(mtime_msg)
 271 
 272     if hints:
 273         request.write(searchHints(f, hints))
 274 
 275     # Search stats
 276     request.write(results.stats(request, request.formatter, hitsFrom))
 277 
 278     # Then search results
 279     info = not titlesearch
 280     if context:
 281         output = results.pageListWithContext(request, request.formatter,
 282                 info=info, context=context, hitsFrom=hitsFrom, hitsInfo=1)
 283     else:
 284         output = results.pageList(request, request.formatter, info=info,
 285                 hitsFrom=hitsFrom, hitsInfo=1)
 286 
 287     request.write(output)
 288 
 289     request.write(request.formatter.endContent())
 290     request.theme.send_footer(pagename)
 291     request.theme.send_closing_html()

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2009-06-25 06:54:13, 114.2 KB) [[attachment:allmimetypes.png]]
  • [get | view] (2009-06-24 22:09:59, 1.8 KB) [[attachment:fullsearch.diff]]
  • [get | view] (2009-06-24 22:09:44, 10.9 KB) [[attachment:fullsearch_new-1.8.2-1.py]]
  • [get | view] (2009-06-24 22:09:33, 10.9 KB) [[attachment:fullsearch_new.py]]
  • [get | view] (2009-06-25 06:54:09, 97.3 KB) [[attachment:onlywikipages.png]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.