-
Notifications
You must be signed in to change notification settings - Fork 7
/
SearchPage.py
365 lines (302 loc) · 13.9 KB
/
SearchPage.py
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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
#!/usr/bin/env python
# -*- mode: python; indent-tabs-mode: nil; -*- coding: utf-8 -*-
"""
SearchPage.py
Copyright 2009-2012 by Marcello Perathoner
Distributable under the GNU General Public License Version 3 or newer.
The various flavors of search page.
"""
from __future__ import unicode_literals
import cherrypy
from libgutenberg.MediaTypes import mediatypes as mt
from libgutenberg.DublinCore import DublinCore
import BaseSearcher
from Page import SearchPage
from i18n_tool import ugettext as _
from i18n_tool import ungettext as __
class BookSearchPage (SearchPage):
""" search term => list of books """
def setup (self, os, sql):
os.sort_orders = ('downloads', 'release_date', 'title', 'random')
os.icon = 'book'
os.class_ += 'booklink'
os.f_format_icon = os.format_icon_titles
if os.sort_order == 'random':
sql.where.append ("pk in (select pk from books order by random() limit 20)")
if len (os.query):
sql.fulltext ('books.tsvec', os.query)
os.title = _("Books: {title}").format (title = os.query)
else:
os.title = _('All Books')
def fixup (self, os):
""" strip marc subfields, add social media hints and facet links """
for e in os.entries:
if '$' in e.title:
e.title = DublinCore.strip_marc_subfields (e.title)
if (os.sort_order == 'release_date' and os.total_results > 0 and os.start_index == 1):
cat = BaseSearcher.Cat ()
cat.title = _('Follow new books on Twitter')
cat.subtitle = _("Follow our new books on Twitter.")
cat.url = 'https://twitter.com/gutenberg_new'
cat.class_ += 'navlink grayed'
cat.icon = 'twitter'
cat.order = 5
os.entries.insert (0, cat)
cat = BaseSearcher.Cat ()
cat.title = _('Follow new books on Facebook')
cat.subtitle = _("Follow the link and like the page to have us post new books to your wall.")
cat.url = 'https://www.facebook.com/gutenberg.new'
cat.class_ += 'navlink grayed'
cat.icon = 'facebook'
cat.order = 5
os.entries.insert (0, cat)
if (len (os.query) and os.start_index == 1):
sql2 = BaseSearcher.SQLStatement ()
sql2.query = "select count (*) from bookshelves"
sql2.fulltext ('bookshelves.tsvec', os.query)
rows = BaseSearcher.SQLSearcher.execute (*sql2.build ())
if rows[0][0] > 0:
cat = BaseSearcher.Cat ()
cat.rel = 'related'
cat.title = _('Bookshelves')
cat.subtitle = __('One bookshelf matches your query.',
'{count} bookshelves match your search.',
rows[0][0]).format (count = rows[0][0])
cat.url = os.url ('bookshelf_search', query = os.query)
cat.class_ += 'navlink grayed'
cat.icon = 'bookshelf'
cat.order = 3
os.entries.insert (0, cat)
sql2 = BaseSearcher.SQLStatement ()
sql2.query = "select count (*) from subjects"
sql2.fulltext ('subjects.tsvec', os.query)
rows = BaseSearcher.SQLSearcher.execute (*sql2.build ())
if rows[0][0] > 0:
cat = BaseSearcher.Cat ()
cat.rel = 'related'
cat.title = _('Subjects')
cat.subtitle = __('One subject heading matches your search.',
'{count} subject headings match your search.',
rows[0][0]).format (count = rows[0][0])
cat.url = os.url ('subject_search', query = os.query)
cat.class_ += 'navlink grayed'
cat.icon = 'subject'
cat.order = 3
os.entries.insert (0, cat)
sql2 = BaseSearcher.SQLStatement ()
sql2.query = "select count (*) from authors"
sql2.fulltext ('authors.tsvec', os.query)
rows = BaseSearcher.SQLSearcher.execute (*sql2.build ())
if rows[0][0] > 0:
cat = BaseSearcher.Cat ()
cat.rel = 'related'
cat.title = _('Authors')
cat.subtitle = __('One author name matches your search.',
'{count} author names match your search.',
rows[0][0]).format (count = rows[0][0])
cat.url = os.url ('author_search', query = os.query)
cat.class_ += 'navlink grayed'
cat.icon = 'author'
cat.order = 3
os.entries.insert (0, cat)
class AuthorSearchPage (SearchPage):
""" name => list of authors """
def setup (self, os, sql):
os.f_format_subtitle = os.format_subtitle
os.f_format_url = BaseSearcher.SearchUrlFormatter ('author')
os.f_format_thumb_url = os.format_none
os.sort_orders = ('downloads', 'quantity', 'alpha', 'release_date')
os.icon = 'author'
os.class_ += 'navlink'
os.title = _('All Authors')
sql.query = """
SELECT
authors.author as title,
coalesce (authors.born_floor || '', '') || '-' ||
coalesce (authors.died_floor || '', '') as subtitle,
authors.pk as pk,
max (books.release_date) as release_date,
sum (books.downloads) as downloads,
count (books.pk) as quantity"""
sql.from_ = ('authors', 'mn_books_authors as mn', 'books')
sql.groupby += ('authors.author', 'subtitle', 'authors.pk')
sql.where.append ('authors.pk = mn.fk_authors')
sql.where.append ('books.pk = mn.fk_books')
if len (os.query):
sql.fulltext ('authors.tsvec', os.query)
os.title = _("Authors: {author}").format (author = os.query)
else:
sql.where.append ("authors.author not in ('Various', 'Anonymous', 'Unknown')")
class SubjectSearchPage (SearchPage):
""" term => list of subects """
def setup (self, os, sql):
os.f_format_url = BaseSearcher.SearchUrlFormatter ('subject')
os.f_format_thumb_url = os.format_none
os.sort_orders = ('downloads', 'quantity', 'alpha', 'release_date')
os.icon = 'subject'
os.class_ += 'navlink'
os.title = _('All Subjects')
sql.query = """
SELECT
subjects.subject as title,
subjects.pk as pk,
max (books.release_date) as release_date,
sum (books.downloads) as downloads,
count (books.pk) as quantity"""
sql.from_ = ('subjects', 'mn_books_subjects as mn', 'books')
sql.groupby += ('subjects.subject', 'subjects.pk')
sql.where.append ('subjects.pk = mn.fk_subjects')
sql.where.append ('books.pk = mn.fk_books')
if len (os.query):
sql.fulltext ('subjects.tsvec', os.query)
os.title = _("Subjects: {subject}").format (subject = os.query)
class BookshelfSearchPage (SearchPage):
""" term => list of bookshelves """
def setup (self, os, sql):
os.f_format_url = BaseSearcher.SearchUrlFormatter ('bookshelf')
os.f_format_thumb_url = os.format_none
os.sort_orders = ('downloads', 'quantity', 'alpha', 'release_date', 'authors')
os.icon = 'bookshelf'
os.class_ += 'navlink'
os.title = _('All Bookshelves')
sql.query = """
SELECT
bookshelves.bookshelf as title,
bookshelves.pk as pk,
max (books.release_date) as release_date,
sum (books.downloads) as downloads,
count (books.pk) as quantity"""
sql.from_ = ('bookshelves', 'mn_books_bookshelves as mn', 'books')
sql.groupby += ('bookshelves.bookshelf', 'bookshelves.pk')
sql.where.append ('bookshelves.pk = mn.fk_bookshelves')
sql.where.append ('books.pk = mn.fk_books')
if len (os.query):
sql.fulltext ('bookshelves.tsvec', os.query)
os.title = _("Bookshelves: {bookshelf}").format (bookshelf = os.query)
class AuthorPage (SearchPage):
""" author id => books by author """
def setup (self, os, sql):
os.sort_orders = ('downloads', 'title', 'release_date')
os.title_icon = 'author'
os.icon = 'book'
os.class_ += 'booklink'
os.f_format_icon = os.format_icon_titles
os.author = BaseSearcher.sql_get (
"select author from authors where pk = %(pk)s", pk = os.id)
os.title = _('Books by {author}').format (author = os.author)
sql.from_.append ('mn_books_authors as mn')
sql.where.append ('books.pk = mn.fk_books')
sql.where.append ("mn.fk_authors = %(fk_authors)s")
sql.params['fk_authors'] = os.id
def fixup (self, os):
for e in os.entries:
if '$' in e.title:
e.title = DublinCore.strip_marc_subfields (e.title)
if (os.start_index == 1 and len (os.entries) > 0):
# browse-by-author page for maintainers
if 'is-catalog-maintainer' in cherrypy.request.cookie:
cat = BaseSearcher.Cat ()
cat.type = mt.html
cat.rel = 'related'
cat.title = _('Browse by Author')
cat.url = "/browse/authors/%s#a%d" % (os.author[:1].lower (), os.id)
cat.class_ += 'navlink grayed'
cat.icon = 'internal'
cat.order = 9
os.entries.insert (0, cat)
# wikipedia links etc.
rows = BaseSearcher.SQLSearcher.execute (
"""SELECT url, description AS title FROM author_urls
WHERE fk_authors = %(fk_authors)s""",
{ 'fk_authors': os.id } )
for row in rows:
cat = BaseSearcher.Cat ()
cat.type = mt.html
cat.rel = 'related'
cat.title = _('See also: {title}').format (title = row.title)
cat.url = row.url
cat.class_ += 'navlink grayed'
cat.icon = 'external'
cat.order = 8
os.entries.insert (0, cat)
# author aliases
if os.format == 'html':
rows = BaseSearcher.SQLSearcher.execute (
"""SELECT alias AS title FROM aliases
WHERE fk_authors = %(fk_authors)s AND alias_heading = 1""",
{ 'fk_authors': os.id }
)
for row in rows:
cat = BaseSearcher.Cat ()
cat.title = _('Alias {alias}').format (alias = row.title)
cat.class_ += 'grayed'
cat.icon = 'alias'
cat.order = 7
os.entries.insert (0, cat)
class SubjectPage (SearchPage):
""" subject id => books about subject """
def setup (self, os, sql):
os.sort_orders = ('downloads', 'title', 'release_date')
os.title_icon = 'subject'
os.icon = 'book'
os.class_ += 'booklink'
os.f_format_icon = os.format_icon_titles
os.subject = BaseSearcher.sql_get (
"select subject from subjects where pk = %(pk)s", pk = os.id)
os.title = _('Books about {subject}').format (subject = os.subject)
sql.from_.append ('mn_books_subjects as mn')
sql.where.append ('books.pk = mn.fk_books')
sql.where.append ("mn.fk_subjects = %(fk_subjects)s")
sql.params['fk_subjects'] = os.id
class BookshelfPage (SearchPage):
""" bookshelf id => books on bookshelf """
def setup (self, os, sql):
os.sort_orders = ('downloads', 'title', 'author', 'release_date')
os.title_icon = 'bookshelf'
os.icon = 'book'
os.class_ += 'booklink'
os.f_format_icon = os.format_icon_titles
os.bookshelf = BaseSearcher.sql_get (
"select bookshelf from bookshelves where pk = %(pk)s", pk = os.id)
os.title = _('Books in {bookshelf}').format (bookshelf = os.bookshelf)
sql.from_.append ('mn_books_bookshelves as mn')
sql.where.append ('books.pk = mn.fk_books')
sql.where.append ("mn.fk_bookshelves = %(fk_bookshelves)s")
sql.params['fk_bookshelves'] = os.id
class AlsoDownloadedPage (SearchPage):
""" ebook id => books people also downloaded """
def setup (self, os, sql):
os.sort_orders = ('downloads', )
os.icon = 'book'
os.class_ += 'booklink'
os.f_format_icon = os.format_icon_titles
os.title = _('Readers also downloaded')
sql.query = """
SELECT
books.pk,
books.title,
books.filing,
books.author,
books.release_date,
books.fk_categories,
books.fk_langs,
books.coverpages,
d.dl as downloads
FROM
v_appserver_books_4 as books
JOIN (
SELECT
s1.fk_books as pk, count (s1.id) as dl
FROM
scores.also_downloads as s1,
scores.also_downloads as s2
WHERE s2.fk_books = %(fk_books)s
AND s1.fk_books != %(fk_books)s
AND s1.id = s2.id
GROUP BY s1.fk_books) as d
ON d.pk = books.pk"""
sql.from_ = ()
sql.params['fk_books'] = os.id
def finalize (self, os):
# one page is enough
os.show_next_page_link = False