Back to index

plone3  3.1.7
livesearch_reply.py
Go to the documentation of this file.
00001 ## Script (Python) "livescript_reply"
00002 ##bind container=container
00003 ##bind context=context
00004 ##bind namespace=
00005 ##bind script=script
00006 ##bind subpath=traverse_subpath
00007 ##parameters=q,limit=10,path=None
00008 ##title=Determine whether to show an id in an edit form
00009 
00010 from Products.CMFCore.utils import getToolByName
00011 from Products.CMFPlone import PloneMessageFactory as _
00012 from Products.CMFPlone.browser.navtree import getNavigationRoot
00013 from Products.CMFPlone.utils import safe_unicode
00014 from Products.PythonScripts.standard import url_quote
00015 from Products.PythonScripts.standard import url_quote_plus
00016 
00017 ploneUtils = getToolByName(context, 'plone_utils')
00018 portal_url = getToolByName(context, 'portal_url')()
00019 pretty_title_or_id = ploneUtils.pretty_title_or_id
00020 plone_view = context.restrictedTraverse('@@plone')
00021 
00022 portalProperties = getToolByName(context, 'portal_properties')
00023 siteProperties = getattr(portalProperties, 'site_properties', None)
00024 useViewAction = []
00025 if siteProperties is not None:
00026     useViewAction = siteProperties.getProperty('typesUseViewActionInListings', [])
00027 
00028 # SIMPLE CONFIGURATION
00029 USE_ICON = True
00030 USE_RANKING = False
00031 MAX_TITLE = 29
00032 MAX_DESCRIPTION = 93
00033 
00034 # generate a result set for the query
00035 catalog = context.portal_catalog
00036 
00037 friendly_types = ploneUtils.getUserFriendlyTypes()
00038 
00039 def quotestring(s):
00040     return '"%s"' % s
00041 
00042 def quote_bad_chars(s):
00043     bad_chars = ["(", ")"]
00044     for char in bad_chars:
00045         s = s.replace(char, quotestring(char))
00046     return s
00047 
00048 # for now we just do a full search to prove a point, this is not the
00049 # way to do this in the future, we'd use a in-memory probability based
00050 # result set.
00051 # convert queries to zctextindex
00052 
00053 # XXX really if it contains + * ? or -
00054 # it will not be right since the catalog ignores all non-word
00055 # characters equally like
00056 # so we don't even attept to make that right.
00057 # But we strip these and these so that the catalog does
00058 # not interpret them as metachars
00059 ##q = re.compile(r'[\*\?\-\+]+').sub(' ', q)
00060 for char in '?-+*':
00061     q = q.replace(char, ' ')
00062 r=q.split()
00063 r = " AND ".join(r)
00064 r = quote_bad_chars(r)+'*'
00065 searchterms = url_quote_plus(r)
00066 
00067 site_encoding = context.plone_utils.getSiteEncoding()
00068 if path is None:
00069     path = getNavigationRoot(context)
00070 results = catalog(SearchableText=r, portal_type=friendly_types, path=path)
00071 
00072 searchterm_query = '?searchterm=%s'%url_quote_plus(q)
00073 
00074 RESPONSE = context.REQUEST.RESPONSE
00075 RESPONSE.setHeader('Content-Type', 'text/xml;charset=%s' % site_encoding)
00076 
00077 # replace named entities with their numbered counterparts, in the xml the named ones are not correct
00078 #   ↓      --> ↓
00079 #   …    --> …
00080 legend_livesearch = _('legend_livesearch', default='LiveSearch ↓')
00081 label_no_results_found = _('label_no_results_found', default='No matching results found.')
00082 label_advanced_search = _('label_advanced_search', default='Advanced Search…')
00083 label_show_all = _('label_show_all', default='Show all…')
00084 heading_search_results =  _('heading_search_results', default='Search results…')
00085 
00086 ts = getToolByName(context, 'translation_service')
00087 
00088 output = []
00089 
00090 def write(s):
00091     output.append(safe_unicode(s))
00092 
00093 
00094 if not results:
00095     write('''<h4>%s</h4>''' % ts.translate(heading_search_results))
00096     write('''<ul>''')
00097     write('''<li>%s</li>''' % ts.translate(label_no_results_found))
00098     write('<li><a href="search_form" style="font-weight:normal">%s</a></li>' % ts.translate(label_advanced_search))
00099     write('''</ul>''')
00100 else:
00101     write('''<h4>%s</h4>''' % ts.translate(heading_search_results))
00102     write('''<ul>''')
00103     for result in results[:limit]:
00104 
00105         icon = plone_view.getIcon(result)
00106         itemUrl = result.getURL()
00107         if result.portal_type in useViewAction:
00108             itemUrl += '/view'
00109         itemUrl = itemUrl + searchterm_query
00110 
00111         write('''<li>''')
00112         
00113         full_title = safe_unicode(pretty_title_or_id(result))
00114         if len(full_title) > MAX_TITLE:
00115             display_title = ''.join((full_title[:MAX_TITLE],'...'))
00116         else:
00117             display_title = full_title
00118         full_title = full_title.replace('"', '&quot;')
00119         write('''<a href="%s" title="%s">''' % (itemUrl, full_title))
00120         if icon.url is not None and icon.description is not None:
00121             write('''<img src="%s" alt="%s" width="%i" height="%i" />''' % (icon.url,
00122                                                                             icon.description,
00123                                                                             icon.width,
00124                                                                             icon.height))
00125         
00126         write('''<span class="livesearchResult-title">%s</span>''' % display_title)
00127         write('''<span class="livesearchResult-score">[%s%%]</span>''' % result.data_record_normalized_score_)
00128         display_description = safe_unicode(result.Description)
00129         if len(display_description) > MAX_DESCRIPTION:
00130             display_description = ''.join((display_description[:MAX_DESCRIPTION],'...'))
00131 
00132         if display_description:
00133             write('''<span class="livesearchResult-description">%s</span>''' % (display_description))
00134         write('''</a>''')
00135         write('''</li>''')
00136         full_title, display_title, display_description = None, None, None
00137 
00138     if len(results)>limit:
00139         # add a more... row
00140         write('''<li class="livesearchShowAll">''')
00141         write('''<a href="%s">%s</a>''' % ('search?SearchableText=' + searchterms, ts.translate(label_show_all)))
00142         write('''</li>''')
00143         
00144     write('''</ul>''')
00145 
00146 return '\n'.join(output).encode(site_encoding)
00147