]> git.0d.be Git - panikweb.git/blob - panikweb/paniktags/templatetags/paniktags.py
b6d468dd9398bbf054d7de774ee50d79e40032c9
[panikweb.git] / panikweb / paniktags / templatetags / paniktags.py
1 import email.utils
2 import datetime
3 import json
4 import re
5 import time
6 import uuid
7
8 from django import template
9 from django.conf import settings
10 from django.core.urlresolvers import reverse
11 from django.db.models.query import QuerySet
12 from django.utils.encoding import force_text
13 from django.utils.http import quote
14 from django.utils.six.moves.urllib import parse as urlparse
15
16 from datetime import datetime, timedelta
17
18 from emissions.models import Emission, Episode, NewsItem, SoundFile, Focus
19 from emissions.utils import period_program
20
21 from panikombo.models import Topik
22
23 from panikweb import utils
24 from panikweb import search
25
26 register = template.Library()
27
28 @register.filter(name='zip')
29 def zip_lists(a, b):
30     return zip(a, b)
31
32 @register.inclusion_tag('includes/audio.html', takes_context=True)
33 def audio(context, sound=None, embed=False, display_fragment_name=False):
34     return {
35         'episode': context.get('episode'),
36         'sound': sound,
37         'display_fragment_name': display_fragment_name,
38         'embed': embed,
39     }
40
41 @register.inclusion_tag('listen/nav.html', takes_context=True)
42 def listen_nav(context, date=None, klass=None):
43     return {
44         'class': klass,
45         'categories': context.get('categories'),
46     }
47
48 @register.inclusion_tag('news/nav.html', takes_context=True)
49 def news_nav(context, date=None, klass=None):
50     return {
51         'class': klass,
52         'newsitem': context.get('newsitem'),
53         'categories': context.get('categories'),
54         'news': context.get('news'),
55         'search_query': context.get('search_query'),
56     }
57
58 @register.inclusion_tag('emissions/nav.html', takes_context=True)
59 def emission_nav(context, date=None, klass=None):
60     return {
61         'class': klass,
62         'categories': context.get('categories'),
63         'episodes': context.get('episodes'),
64         'emission': context.get('emission'),
65         'episode': context.get('episode'),
66         'search_query': context.get('search_query'),
67     }
68
69 @register.inclusion_tag('episodes/inline.html', takes_context=True)
70 def episode_inline(context, date=None, model=None, klass=None):
71     return {
72         'class': klass,
73         'episode': context.get('episode'),
74         'date': date,
75     }
76 @register.inclusion_tag('episodes/resume.html', takes_context=True)
77 def episode_resume(context, date=None, model=None, klass=None):
78     return {
79         'model': model,
80         'class': klass,
81         'episode': context.get('episode'),
82         'date': date,
83     }
84
85 @register.inclusion_tag('episodes/detail.html', takes_context=True)
86 def episode_detail(context, date=None):
87     soundfiles = SoundFile.objects.select_related().filter(
88             fragment=True, podcastable=True, episode=context.get('episode'))
89     return {
90         'episode': context.get('episode'),
91         'emission': context.get('emission'),
92         'diffusions': context.get('diffusions'),
93         'soundfiles': soundfiles,
94         'date': date,
95         'topiks': context.get('topiks'),
96     }
97
98 @register.inclusion_tag('emissions/detail.html', takes_context=True)
99 def emission_detail(context, date=None):
100     return {
101         'emission': context.get('emission'),
102         'schedules': context.get('schedules'),
103     }
104
105 @register.inclusion_tag('emissions/resume.html', takes_context=True)
106 def emission_resume(context, date=None):
107     return {
108         'emission': context.get('emission'),
109         'schedules': context.get('schedules'),
110     }
111
112 @register.inclusion_tag('emissions/inline.html', takes_context=True)
113 def emission_inline(context, date=None):
114     return {
115         'emission': context.get('emission'),
116         'schedules': context.get('schedules'),
117     }
118
119 @register.inclusion_tag('soundfiles/resume.html')
120 def soundfile_resume(soundfile, date=None):
121     return {'soundfile': soundfile,
122             'date': date}
123
124 @register.inclusion_tag('includes/player.html', takes_context=True)
125 def player(context):
126
127     return {
128         'unique': uuid.uuid4(),
129         'soundfiles': context.get('soundfiles'),
130     }
131
132 @register.inclusion_tag('includes/metaNav.html', takes_context=True)
133 def metanav(context, active=None):
134     request_path = context['request'].path
135     section = 'About'
136     if request_path == '/':
137         section = 'Home'
138     elif request_path.startswith('/actus/'):
139         section = 'News'
140     elif request_path.startswith('/sons/'):
141         section = 'Listen'
142     elif request_path.startswith('/topiks'):
143         section = 'Topiks'
144     elif request_path.startswith('/emissions') or request_path == '/grille' or request_path == '/programme/':
145         section = 'Emissions'
146     elif request_path == '/recherche/':
147         section = 'Search'
148     return {
149         'LANGUAGE_CODE': context.get('LANGUAGE_CODE'),
150         'sectionName': section,
151         }
152
153 @register.inclusion_tag('includes/week.html')
154 def weekview(year=None, week=None):
155     year = year if year else datetime.today().isocalendar()[0]
156     week = week if week else datetime.today().isocalendar()[1]
157
158     date = utils.tofirstdayinisoweek(year, week)
159     date = datetime(*date.timetuple()[:3])
160
161     program = period_program(date, date+timedelta(days=7))
162     days = []
163     for day in range(7):
164         days.append({'cells': [x for x in program if x.is_on_weekday(day+1)],
165                      'datetime': date+timedelta(days=day)})
166
167     return {
168         'days': days,
169         'week': week,
170         'year': year,
171     }
172
173 @register.inclusion_tag('includes/week-nav.html')
174 def weeknav(year=None, week=None, weekday=None):
175     year = year if year else datetime.today().isocalendar()[0]
176     week = week if week else datetime.today().isocalendar()[1]
177     weekday = weekday if weekday is not None else datetime.today().weekday()
178
179     date = utils.tofirstdayinisoweek(year, week)
180     date = datetime(*date.timetuple()[:3])
181
182     days = []
183     for day in range(7):
184         days.append({'datetime': date+timedelta(days=day)})
185
186     previous_week = date - timedelta(days=7)
187     previous_week_year, previous_week_no = previous_week.isocalendar()[:2]
188
189     next_week = date + timedelta(days=7)
190     next_week_year, next_week_no = next_week.isocalendar()[:2]
191
192     return {
193         'days': days,
194         'weekday': weekday,
195         'week': week,
196         'year': year,
197         'previous_week_year': previous_week_year,
198         'previous_week_no': previous_week_no,
199         'next_week_year': next_week_year,
200         'next_week_no': next_week_no,
201     }
202
203
204 @register.inclusion_tag('news/inline.html', takes_context=True)
205 def news_inline(context, klass=None, logo=None):
206     return {
207             'content': context.get('content'),
208             'class': klass,
209             'logo': logo
210     }
211
212 @register.inclusion_tag('news/roll.html')
213 def newsroll():
214     return {
215         'news': Focus.objects.filter(current=True).select_related('emission', 'newsitem',
216             'soundfile', 'episode', 'newsitem__category').order_by('?')[:3]
217     }
218
219
220 @register.filter
221 def jsonify(object):
222     if isinstance(object, QuerySet):
223         return serialize('json', object)
224     return json.dumps(object)
225
226 @register.filter
227 def strreplace ( string, args ): 
228     find  = args.split(',')[0]
229     replace = args.split(',')[1]
230     return string.replace(find,replace)
231
232 @register.filter
233 def replace ( string, args ): 
234     search  = args.split(args[0])[1]
235     replace = args.split(args[0])[2]
236
237     return re.sub( search, replace, string )
238
239
240 def remove_facet(facet_id, url, facet):
241     scheme, netloc, path, query, fragment = list(urlparse.urlsplit(str(url)))
242     facet = '%s_exact:%s' % (facet_id, facet.encode('utf-8'))
243     query_string = urlparse.parse_qsl(query)
244     query_string = [x for x in query_string if not (
245         x[0] == 'selected_facets' and x[1] == facet)]
246     query = '&'.join(['%s=%s' % x for x in query_string])
247     url = urlparse.urlunsplit([scheme, netloc, path, query, None])
248     return force_text(re.sub(r'&page=\d+', '', url), 'utf-8')
249
250 @register.filter
251 def remove_tag_facet(url, facet):
252     return remove_facet('tags', url, facet)
253
254 @register.filter
255 def remove_category_facet(url, facet):
256     return remove_facet('categories', url, facet)
257
258
259 @register.filter
260 def remove_news_category_facet(url, facet):
261     return remove_facet('news_categories', url, facet)
262
263 @register.filter
264 def remove_format_facet(url, facet):
265     return remove_facet('format', url, facet)
266
267
268 def append_facet(facet_id, url, facet):
269     facet = quote(facet.encode('utf-8'), safe='')
270     if not '?' in url:
271         url = url + '?'
272     return re.sub(r'&page=\d+', '', url + '&selected_facets=%s_exact:%s' % (facet_id, facet))
273
274 @register.filter
275 def append_tag_facet(url, facet):
276     return append_facet('tags', url, facet)
277
278 @register.filter
279 def append_category_facet(url, facet):
280     return append_facet('categories', url, facet)
281
282 @register.filter
283 def append_news_category_facet(url, facet):
284     return append_facet('news_categories', url, facet)
285
286 @register.filter
287 def append_format_facet(url, facet):
288     return append_facet('format', url, facet)
289
290
291 @register.tag
292 def search_result_template(parser, token):
293     try:
294         tag_name, result_str = token.split_contents()
295     except ValueError:
296         raise template.TemplateSyntaxError("%r tag requires exactly one argument" % token.contents.split()[0])
297     return FormatSearchResultNode(result_str)
298
299
300 class FormatSearchResultNode(template.Node):
301     def __init__(self, result_str):
302         self.result_var = template.Variable(result_str)
303
304     def render(self, context):
305         result = self.result_var.resolve(context)
306         dir_mapping = {
307             'newsitem': 'news',
308             'emission': 'emissions',
309             'episode': 'episodes'
310         }
311         t = template.loader.get_template('%s/search_result.html' % dir_mapping.get(result.model_name))
312         return t.render({'result': result})
313
314
315 @register.inclusion_tag('includes/piwik.html')
316 def piwik():
317     return {'enabled': settings.ENABLE_PIWIK}
318
319
320 @register.filter
321 def rfc822(datetime):
322     if datetime is None:
323         return ''
324     return email.utils.formatdate(time.mktime(datetime.timetuple()))
325
326 @register.inclusion_tag('includes/related.html', takes_context=False)
327 def related_objects(object):
328     sqs = search.MoreLikeThisSearchQuerySet().models(Emission, Episode, NewsItem)
329     return {'more_like_this': sqs.more_like_this(object)[:12]}
330
331 @register.inclusion_tag('includes/topik.html', takes_context=True)
332 def topik(context, topik):
333     return {'topik': topik}
334
335 @register.filter
336 def get_focus_url(object):
337     if object.newsitem:
338         return reverse('newsitem-view', kwargs={'slug': object.newsitem.slug})
339     if object.emission:
340         return reverse('emission-view', kwargs={'slug': object.emission.slug})
341     if object.episode:
342         return reverse('episode-view', kwargs={
343             'slug': object.episode.slug, 'emission_slug': object.episode.emission.slug})
344     if object.soundfile:
345         return reverse('episode-view', kwargs={
346             'slug': object.soundfile.episode.slug,
347             'emission_slug': object.soundfile.episode.emission.slug})
348     if object.page:
349         return object.page.get_online_url()
350     return ''
351
352 @register.filter
353 def facet_tag(tag):
354     return tag.name
355
356
357 @register.filter
358 def image_file(page):
359     try:
360         matching_topik = Topik.objects.get(page=page)
361         return matching_topik.image
362     except Topik.DoesNotExist:
363         pass
364     return None
365
366
367 @register.filter
368 def set_absolute_urls(text):
369     text = text.replace('src="/', 'src="%s' % settings.WEBSITE_BASE_URL)
370     text = text.replace('href="/', 'href="%s' % settings.WEBSITE_BASE_URL)
371     return text
372
373 @register.filter
374 def as_absolute_url(url):
375     if url.startswith('/'):
376         url = settings.WEBSITE_BASE_URL + url.lstrip('/')
377     return url