summaryrefslogtreecommitdiffstats
path: root/src/collective/dms/thesaurus/browser/thesaurusview.py
blob: 9f8412d56f88be23e45aedf137d30a93d3be00f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
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()]

        startswith = []
        intermediate = []
        other = []
        q = query_string.lower()
        regex = re.compile(r"[\s'()]")
        items = self.getItems(query_string)
        done = {}
        for normalized, title, id in items:
            for term in query_terms:
                if not term in normalized.lower():
                    break
                else:
                    done[id] = True
                    item = '%s|%s' % (title, id)
                    if normalized.lower().startswith(q):
                        startswith.append((normalized, item))
                        continue
                    for word in regex.split(normalized):
                        if word.lower().startswith(q):
                            intermediate.append((normalized, item))
                            break
                    else:
                        other.append((normalized, item))

        for normalized, title, id in items:
            if done.get(id):
                continue
            item = '%s|%s' % (title, id)
            other.append((normalized, item))

        startswith.sort()
        intermediate.sort()
        other.sort()

        result = list()
        for _list in (startswith, intermediate, other):
            for item in _list:
                result.append(item[1])
                if len(result) > 29:
                    return '\n'.join(result)
        return '\n'.join(result)