import re from zope.interface import implementer from zope.interface import implements from zope.interface import Interface from zope.component import adapter from zope import schema from zope.browserpage.viewpagetemplatefile import ViewPageTemplateFile from z3c.form.interfaces import IFormLayer, IFieldWidget, ITextWidget from z3c.form.widget import FieldWidget from z3c.form import form, field from z3c.form.browser import text from plone.formwidget.autocomplete.widget import AutocompleteSelectionWidget from plone.formwidget.autocomplete.interfaces import IAutocompleteWidget from plone.dexterity.browser.view import DefaultView from plone.i18n.normalizer.fr import normalizer from Products.Five import BrowserView from Products.CMFCore.utils import getToolByName from collective.dms.thesaurus import _ class IAutocompleteSearchWidget(IAutocompleteWidget): """Simple autocomplete search input widget """ class AutocompleteSearchWidget(AutocompleteSelectionWidget): """Search widget with autocompletion. """ implements(IAutocompleteSearchWidget) klass = u'autocomplete-search-widget' input_template = ViewPageTemplateFile('thesaurus_search_input.pt') display_template = ViewPageTemplateFile('thesaurus_search_input.pt') @adapter(IAutocompleteSearchWidget, IFormLayer) @implementer(IFieldWidget) def AutocompleteSearchFieldWidget(field, request): return FieldWidget(field, AutocompleteSearchWidget(request)) class IKeywordSearchWidget(ITextWidget): pass class KeywordSearchWidget(text.TextWidget): implements(IKeywordSearchWidget) klass = u'keyword-search' def KeywordSearchFieldWidget(field, request): return FieldWidget(field, KeywordSearchWidget(request)) class IThesaurusForm(Interface): keyword_search = schema.TextLine( title=_(u"Quick Search"), description=_(u"Search for a keyword in this Thesaurus"), required=False) class DmsThesaurusForm(form.Form): implements(IThesaurusForm) fields = field.Fields(IThesaurusForm) fields['keyword_search'].widgetFactory = KeywordSearchFieldWidget ignoreContext = True template = ViewPageTemplateFile('thesaurus_form.pt') class DmsThesaurusView(DefaultView): def renderForm(self): form = DmsThesaurusForm(self.context, self.request) form.update() return form.render() class ListKeywordsView(BrowserView): _items = None def getItems(self, query=None): context = self.context if self._items is not None: return self._items titles = list() self._items = list() kwargs = {} if query: kwargs['SearchableText'] = query catalog = getToolByName(context, 'portal_catalog') path = '/'.join(context.getPhysicalPath()) for brain in catalog(portal_type='dmskeyword', path={'query': path,'depth': 1}, **kwargs): obj = brain.getObject() normalized = normalizer.normalize(obj.title).lower() if normalized in titles: continue self._items.append((normalized, obj.title, obj.id)) titles.append(normalized) for equiv in (obj.equivs or []): if not equiv: continue normalized = normalizer.normalize(equiv).lower() if normalized in titles: continue self._items.append((normalized, equiv, obj.id)) def cmp_keyword(x, y): return cmp(x[0].lower(), y[0].lower()) self._items.sort(cmp_keyword) return self._items def __call__(self): self.request.response.setHeader('Content-type', 'text/plain') query_string = unicode(self.request.form.get('q'), 'utf-8') query_terms = [normalizer.normalize(x) for x in query_string.split()] absolute_startswith = [] startswith = [] intermediate = [] other = [] q = query_string.lower() regex = re.compile(r"[\s'()]") items = self.getItems(query_string) for normalized, title, id in items: count_start = 0 count_in = 0 for term in query_terms: for word in regex.split(normalized): if word.lower().startswith(term): count_start += 1 elif term in word.lower(): count_in += 1 item = '%s|%s' % (title, id) if len(query_terms) == 1 and normalized.startswith(query_terms[0]): absolute_startswith.append((normalized, item)) elif len(query_terms) > 1 and count_start == len(query_terms): absolute_startswith.append((normalized, item)) elif count_start >= 1: startswith.append((normalized, item)) elif count_in: intermediate.append((normalized, item)) else: other.append((normalized, item)) absolute_startswith.sort() startswith.sort() intermediate.sort() other.sort() result = list() for _list in (absolute_startswith, startswith, intermediate, other): for item in _list: result.append(item[1]) if len(result) > 29: return '\n'.join(result) return '\n'.join(result)