Switch to unified view

a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
...
...
16
#       under the License.
16
#       under the License.
17
17
18
import re
18
import re
19
import socket
19
import socket
20
from logging import getLogger
20
from logging import getLogger
21
from urllib import urlencode
22
from itertools import imap
21
23
22
import markdown
24
import markdown
23
import jinja2
25
import jinja2
26
from tg import redirect, url
24
from pylons import tmpl_context as c, app_globals as g
27
from pylons import tmpl_context as c, app_globals as g
28
from pylons import request
25
from pysolr import SolrError
29
from pysolr import SolrError
26
30
31
from allura.lib import helpers as h
27
from .markdown_extensions import ForgeExtension
32
from .markdown_extensions import ForgeExtension
28
33
29
log = getLogger(__name__)
34
log = getLogger(__name__)
30
35
31
def solarize(obj):
36
def solarize(obj):
...
...
81
        'mount_point_s:%s' % c.app.config.options.mount_point ]
86
        'mount_point_s:%s' % c.app.config.options.mount_point ]
82
    if not history:
87
    if not history:
83
        fq.append('is_history_b:False')
88
        fq.append('is_history_b:False')
84
    return search(q, fq=fq, rows=rows, short_timeout=short_timeout, ignore_errors=False, **kw)
89
    return search(q, fq=fq, rows=rows, short_timeout=short_timeout, ignore_errors=False, **kw)
85
90
91
92
def search_app(q='', fq=None, **kw):
93
    """Helper for app search.
94
95
    Uses dismax query parser. Matches on `title` and `text`. Handles paging, sorting, etc
96
    """
97
    history = kw.pop('history', None)
98
    if kw.pop('project', False):
99
        redirect(c.project.url() + 'search?' + urlencode(dict(q=q, history=history)))
100
    search_comments = kw.pop('search_comments', None)
101
    limit = kw.pop('limit', None)
102
    page = kw.pop('page', 0)
103
    default = kw.pop('default', 25)
104
    allowed_types = kw.pop('allowed_types', [])
105
    parser = kw.pop('parser', None)
106
    sort = kw.pop('sort', 'score desc')
107
    fq = fq if fq else []
108
    search_error = None
109
    results = []
110
    count = 0
111
    matches = {}
112
    limit, page, start = g.handle_paging(limit, page, default=default)
113
    if not q:
114
        q = ''
115
    else:
116
        # Match on both `title` and `text` by default, using 'dismax' parser.
117
        # Score on `title` matches is boosted, so title match is better than body match.
118
        # It's 'fuzzier' than standard parser, which matches only on `text`.
119
        if search_comments:
120
            allowed_types += ['Post']
121
        search_params = {
122
            'qt': 'dismax',
123
            'qf': 'title^2 text',
124
            'pf': 'title^2 text',
125
            'fq': [
126
                'project_id_s:%s'  % c.project._id,
127
                'mount_point_s:%s' % c.app.config.options.mount_point,
128
                '-deleted_b:true',
129
                'type_s:(%s)' % ' OR '.join(['"%s"' % t for t in allowed_types])
130
            ] + fq,
131
            'hl': 'true',
132
            'hl.simple.pre': '<strong>',
133
            'hl.simple.post': '</strong>',
134
            'sort': sort,
135
        }
136
        if not history:
137
           search_params['fq'].append('is_history_b:False')
138
        if parser == 'standard':
139
            search_params.pop('qt', None)
140
            search_params.pop('qf', None)
141
            search_params.pop('pf', None)
142
        try:
143
            results = search(
144
                q, short_timeout=True, ignore_errors=False,
145
                rows=limit, start=start, **search_params)
146
        except SearchError as e:
147
            search_error = e
148
        if results:
149
            count = results.hits
150
            matches = results.highlighting
151
            def historize_urls(doc):
152
                if doc.get('type_s', '').endswith(' Snapshot'):
153
                    if doc.get('url_s'):
154
                        doc['url_s'] = doc['url_s'] + '?version=%s' % doc.get('version_i')
155
                return doc
156
            def add_matches(doc):
157
                m = matches.get(doc['id'], {})
158
                doc['title_match'] = h.get_first(m, 'title')
159
                doc['text_match'] = h.get_first(m, 'text')
160
                if not doc['text_match']:
161
                    doc['text_match'] = h.get_first(doc, 'text')
162
                return doc
163
            results = imap(historize_urls, results)
164
            results = imap(add_matches, results)
165
166
    # Provide sort urls to the view
167
    score_url = 'score desc'
168
    date_url = 'mod_date_dt desc'
169
    try:
170
        field, order = sort.split(' ')
171
    except ValueError:
172
        field, order = 'score', 'desc'
173
    sort = ' '.join([field, 'asc' if order == 'desc' else 'desc'])
174
    if field == 'score':
175
        score_url = sort
176
    elif field == 'mod_date_dt':
177
        date_url = sort
178
    params = request.GET.copy()
179
    params.update({'sort': score_url})
180
    score_url = url(request.path, params=params)
181
    params.update({'sort': date_url})
182
    date_url = url(request.path, params=params)
183
    return dict(q=q, history=history, results=results or [],
184
                count=count, limit=limit, page=page, search_error=search_error,
185
                sort_score_url=score_url, sort_date_url=date_url,
186
                sort_field=field)
187
188
86
def find_shortlinks(text):
189
def find_shortlinks(text):
87
    md = markdown.Markdown(
190
    md = markdown.Markdown(
88
        extensions=['codehilite', ForgeExtension(), 'tables'],
191
        extensions=['codehilite', ForgeExtension(), 'tables'],
89
        output_format='html4')
192
        output_format='html4')
90
    md.convert(text)
193
    md.convert(text)