| 1 | # -*- coding: utf-8 |
|---|
| 2 | from datetime import datetime, timedelta |
|---|
| 3 | import urllib |
|---|
| 4 | |
|---|
| 5 | from django import template |
|---|
| 6 | from django.core.urlresolvers import reverse |
|---|
| 7 | from django.core.cache import cache |
|---|
| 8 | from django.utils.safestring import mark_safe |
|---|
| 9 | from django.template import RequestContext |
|---|
| 10 | from django.utils.encoding import smart_unicode |
|---|
| 11 | from django.db import settings |
|---|
| 12 | from django.utils.html import escape |
|---|
| 13 | from django.utils.translation import ugettext as _ |
|---|
| 14 | from django.utils import dateformat |
|---|
| 15 | from django.utils.hashcompat import md5_constructor |
|---|
| 16 | from django.contrib.humanize.templatetags.humanize import naturalday |
|---|
| 17 | |
|---|
| 18 | from djangobb_forum.models import Forum, Topic, Post, PostTracking, Report |
|---|
| 19 | from djangobb_forum import settings as forum_settings |
|---|
| 20 | |
|---|
| 21 | if forum_settings.PM_SUPPORT: |
|---|
| 22 | from messages.models import inbox_count_for |
|---|
| 23 | |
|---|
| 24 | register = template.Library() |
|---|
| 25 | |
|---|
| 26 | # TODO: |
|---|
| 27 | # * rename all tags with forum_ prefix |
|---|
| 28 | |
|---|
| 29 | @register.filter |
|---|
| 30 | def profile_link(user): |
|---|
| 31 | data = u'<a href="%s">%s</a>' % (\ |
|---|
| 32 | reverse('djangobb:forum_profile', args=[user.username]), user.username) |
|---|
| 33 | return mark_safe(data) |
|---|
| 34 | |
|---|
| 35 | |
|---|
| 36 | @register.tag |
|---|
| 37 | def forum_time(parser, token): |
|---|
| 38 | try: |
|---|
| 39 | tag, time = token.split_contents() |
|---|
| 40 | except ValueError: |
|---|
| 41 | raise template.TemplateSyntaxError('forum_time requires single argument') |
|---|
| 42 | else: |
|---|
| 43 | return ForumTimeNode(time) |
|---|
| 44 | |
|---|
| 45 | |
|---|
| 46 | class ForumTimeNode(template.Node): |
|---|
| 47 | def __init__(self, time): |
|---|
| 48 | self.time = template.Variable(time) |
|---|
| 49 | |
|---|
| 50 | def render(self, context): |
|---|
| 51 | time = self.time.resolve(context) |
|---|
| 52 | formated_time = u'%s %s' % (naturalday(time), time.strftime('%H:%M:%S')) |
|---|
| 53 | formated_time = mark_safe(formated_time) |
|---|
| 54 | return formated_time |
|---|
| 55 | |
|---|
| 56 | |
|---|
| 57 | # TODO: this old code requires refactoring |
|---|
| 58 | @register.inclusion_tag('forum/pagination.html',takes_context=True) |
|---|
| 59 | def pagination(context, adjacent_pages=1): |
|---|
| 60 | """ |
|---|
| 61 | Return the list of A tags with links to pages. |
|---|
| 62 | """ |
|---|
| 63 | |
|---|
| 64 | page_list = range( |
|---|
| 65 | max(1, context['page'] - adjacent_pages), |
|---|
| 66 | min(context['pages'], context['page'] + adjacent_pages) + 1) |
|---|
| 67 | lower_page = None |
|---|
| 68 | higher_page = None |
|---|
| 69 | |
|---|
| 70 | if not 1 == context['page']: |
|---|
| 71 | lower_page = context['page'] - 1 |
|---|
| 72 | |
|---|
| 73 | if not 1 in page_list: |
|---|
| 74 | page_list.insert(0,1) |
|---|
| 75 | if not 2 in page_list: |
|---|
| 76 | page_list.insert(1,'.') |
|---|
| 77 | |
|---|
| 78 | if not context['pages'] == context['page']: |
|---|
| 79 | higher_page = context['page'] + 1 |
|---|
| 80 | |
|---|
| 81 | if not context['pages'] in page_list: |
|---|
| 82 | if not context['pages'] - 1 in page_list: |
|---|
| 83 | page_list.append('.') |
|---|
| 84 | page_list.append(context['pages']) |
|---|
| 85 | get_params = '&'.join(['%s=%s' % (x[0], x[1]) for x in |
|---|
| 86 | context['request'].GET.iteritems() if (x[0] != 'page' and x[0] != 'per_page')]) |
|---|
| 87 | if get_params: |
|---|
| 88 | get_params = '?%s&' % get_params |
|---|
| 89 | else: |
|---|
| 90 | get_params = '?' |
|---|
| 91 | |
|---|
| 92 | return { |
|---|
| 93 | 'get_params': get_params, |
|---|
| 94 | 'lower_page': lower_page, |
|---|
| 95 | 'higher_page': higher_page, |
|---|
| 96 | 'page': context['page'], |
|---|
| 97 | 'pages': context['pages'], |
|---|
| 98 | 'page_list': page_list, |
|---|
| 99 | 'per_page': context['per_page'], |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | |
|---|
| 103 | @register.inclusion_tag('forum/lofi/pagination.html',takes_context=True) |
|---|
| 104 | def lofi_pagination(context): |
|---|
| 105 | page_list = range(1, context['pages'] + 1) |
|---|
| 106 | paginator = context['paginator'] |
|---|
| 107 | |
|---|
| 108 | get_params = '&'.join(['%s=%s' % (x[0],','.join(x[1])) for x in |
|---|
| 109 | context['request'].GET.iteritems() if (not x[0] == 'page' and not x[0] == 'per_page')]) |
|---|
| 110 | if get_params: |
|---|
| 111 | get_params = '?%s&' % get_params |
|---|
| 112 | else: |
|---|
| 113 | get_params = '?' |
|---|
| 114 | |
|---|
| 115 | return { |
|---|
| 116 | 'get_params': get_params, |
|---|
| 117 | 'page_list': page_list, |
|---|
| 118 | 'paginator': paginator, |
|---|
| 119 | } |
|---|
| 120 | |
|---|
| 121 | |
|---|
| 122 | @register.simple_tag |
|---|
| 123 | def link(object, anchor=u''): |
|---|
| 124 | """ |
|---|
| 125 | Return A tag with link to object. |
|---|
| 126 | """ |
|---|
| 127 | |
|---|
| 128 | url = hasattr(object,'get_absolute_url') and object.get_absolute_url() or None |
|---|
| 129 | anchor = anchor or smart_unicode(object) |
|---|
| 130 | return mark_safe('<a href="%s">%s</a>' % (url, escape(anchor))) |
|---|
| 131 | |
|---|
| 132 | |
|---|
| 133 | @register.simple_tag |
|---|
| 134 | def lofi_link(object, anchor=u''): |
|---|
| 135 | """ |
|---|
| 136 | Return A tag with lofi_link to object. |
|---|
| 137 | """ |
|---|
| 138 | |
|---|
| 139 | url = hasattr(object,'get_absolute_url') and object.get_absolute_url() or None |
|---|
| 140 | anchor = anchor or smart_unicode(object) |
|---|
| 141 | return mark_safe('<a href="%slofi">%s</a>' % (url, escape(anchor))) |
|---|
| 142 | |
|---|
| 143 | |
|---|
| 144 | @register.filter |
|---|
| 145 | def has_unreads(topic, user): |
|---|
| 146 | """ |
|---|
| 147 | Check if topic has messages which user didn't read. |
|---|
| 148 | """ |
|---|
| 149 | if not user.is_authenticated() or\ |
|---|
| 150 | (user.posttracking.last_read is not None and\ |
|---|
| 151 | user.posttracking.last_read > topic.last_post.created): |
|---|
| 152 | return False |
|---|
| 153 | else: |
|---|
| 154 | if isinstance(user.posttracking.topics, dict): |
|---|
| 155 | if topic.last_post.id > user.posttracking.topics.get(str(topic.id), 0): |
|---|
| 156 | return True |
|---|
| 157 | else: |
|---|
| 158 | return False |
|---|
| 159 | return True |
|---|
| 160 | |
|---|
| 161 | |
|---|
| 162 | @register.filter |
|---|
| 163 | def forum_moderated_by(topic, user): |
|---|
| 164 | """ |
|---|
| 165 | Check if user is moderator of topic's forum. |
|---|
| 166 | """ |
|---|
| 167 | |
|---|
| 168 | return user.is_superuser or user in topic.forum.moderators.all() |
|---|
| 169 | |
|---|
| 170 | |
|---|
| 171 | @register.filter |
|---|
| 172 | def forum_editable_by(post, user): |
|---|
| 173 | """ |
|---|
| 174 | Check if the post could be edited by the user. |
|---|
| 175 | """ |
|---|
| 176 | |
|---|
| 177 | if user.is_superuser: |
|---|
| 178 | return True |
|---|
| 179 | if post.user == user: |
|---|
| 180 | return True |
|---|
| 181 | if user in post.topic.forum.moderators.all(): |
|---|
| 182 | return True |
|---|
| 183 | return False |
|---|
| 184 | |
|---|
| 185 | |
|---|
| 186 | @register.filter |
|---|
| 187 | def forum_posted_by(post, user): |
|---|
| 188 | """ |
|---|
| 189 | Check if the post is writed by the user. |
|---|
| 190 | """ |
|---|
| 191 | |
|---|
| 192 | return post.user == user |
|---|
| 193 | |
|---|
| 194 | |
|---|
| 195 | @register.filter |
|---|
| 196 | def forum_equal_to(obj1, obj2): |
|---|
| 197 | """ |
|---|
| 198 | Check if objects are equal. |
|---|
| 199 | """ |
|---|
| 200 | |
|---|
| 201 | return obj1 == obj2 |
|---|
| 202 | |
|---|
| 203 | |
|---|
| 204 | @register.filter |
|---|
| 205 | def forum_authority(user): |
|---|
| 206 | posts = user.forum_profile.post_count |
|---|
| 207 | if posts >= forum_settings.AUTHORITY_STEP_10: |
|---|
| 208 | return mark_safe('<img src="%sforum/img/authority/vote10.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 209 | elif posts >= forum_settings.AUTHORITY_STEP_9: |
|---|
| 210 | return mark_safe('<img src="%sforum/img/authority/vote9.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 211 | elif posts >= forum_settings.AUTHORITY_STEP_8: |
|---|
| 212 | return mark_safe('<img src="%sforum/img/authority/vote8.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 213 | elif posts >= forum_settings.AUTHORITY_STEP_7: |
|---|
| 214 | return mark_safe('<img src="%sforum/img/authority/vote7.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 215 | elif posts >= forum_settings.AUTHORITY_STEP_6: |
|---|
| 216 | return mark_safe('<img src="%sforum/img/authority/vote6.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 217 | elif posts >= forum_settings.AUTHORITY_STEP_5: |
|---|
| 218 | return mark_safe('<img src="%sforum/img/authority/vote5.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 219 | elif posts >= forum_settings.AUTHORITY_STEP_4: |
|---|
| 220 | return mark_safe('<img src="%sforum/img/authority/vote4.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 221 | elif posts >= forum_settings.AUTHORITY_STEP_3: |
|---|
| 222 | return mark_safe('<img src="%sforum/img/authority/vote3.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 223 | elif posts >= forum_settings.AUTHORITY_STEP_2: |
|---|
| 224 | return mark_safe('<img src="%sforum/img/authority/vote2.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 225 | elif posts >= forum_settings.AUTHORITY_STEP_1: |
|---|
| 226 | return mark_safe('<img src="%sforum/img/authority/vote1.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 227 | else: |
|---|
| 228 | return mark_safe('<img src="%sforum/img/authority/vote0.gif" alt="" >' % (settings.MEDIA_URL)) |
|---|
| 229 | |
|---|
| 230 | |
|---|
| 231 | @register.filter |
|---|
| 232 | def online(user): |
|---|
| 233 | return cache.get(str(user.id)) |
|---|
| 234 | |
|---|
| 235 | |
|---|
| 236 | @register.filter |
|---|
| 237 | def pm_unreads(user): |
|---|
| 238 | if forum_settings.PM_SUPPORT: |
|---|
| 239 | return inbox_count_for(user) |
|---|
| 240 | return None |
|---|
| 241 | |
|---|
| 242 | @register.filter |
|---|
| 243 | def attachment_link(attach): |
|---|
| 244 | from django.template.defaultfilters import filesizeformat |
|---|
| 245 | if attach.content_type in ['image/png', 'image/gif', 'image/jpeg']: |
|---|
| 246 | img = '<img src="%sforum/img/attachment/image.png" alt="attachment" >' % (settings.MEDIA_URL) |
|---|
| 247 | elif attach.content_type in ['application/x-tar', 'application/zip']: |
|---|
| 248 | img = '<img src="%sforum/img/attachment/compress.png" alt="attachment" >' % (settings.MEDIA_URL) |
|---|
| 249 | elif attach.content_type in ['text/plain']: |
|---|
| 250 | img = '<img src="%sforum/img/attachment/text.png" alt="attachment" >' % (settings.MEDIA_URL) |
|---|
| 251 | elif attach.content_type in ['application/msword']: |
|---|
| 252 | img = '<img src="%sforum/img/attachment/doc.png" alt="attachment" >' % (settings.MEDIA_URL) |
|---|
| 253 | else: |
|---|
| 254 | img = '<img src="%sforum/img/attachment/unknown.png" alt="attachment" >' % (settings.MEDIA_URL) |
|---|
| 255 | attachment = '%s <a href="%s">%s</a> (%s)' % (img, attach.get_absolute_url(), attach.name, filesizeformat(attach.size)) |
|---|
| 256 | return mark_safe(attachment) |
|---|
| 257 | |
|---|
| 258 | |
|---|
| 259 | @register.simple_tag |
|---|
| 260 | def new_reports(): |
|---|
| 261 | return Report.objects.filter(zapped=False).count() |
|---|
| 262 | |
|---|
| 263 | |
|---|
| 264 | @register.simple_tag |
|---|
| 265 | def gravatar(email): |
|---|
| 266 | if forum_settings.GRAVATAR_SUPPORT: |
|---|
| 267 | size = max(forum_settings.AVATAR_WIDTH, forum_settings.AVATAR_HEIGHT) |
|---|
| 268 | url = "http://www.gravatar.com/avatar.php?" |
|---|
| 269 | url += urllib.urlencode({ |
|---|
| 270 | 'gravatar_id': md5_constructor(email.lower()).hexdigest(), |
|---|
| 271 | 'size': size, |
|---|
| 272 | 'default': forum_settings.GRAVATAR_DEFAULT, |
|---|
| 273 | }) |
|---|
| 274 | return url |
|---|
| 275 | else: |
|---|
| 276 | return '' |
|---|
| 277 | |
|---|
| 278 | @register.simple_tag |
|---|
| 279 | def set_theme_style(user): |
|---|
| 280 | theme_style = '' |
|---|
| 281 | selected_theme = '' |
|---|
| 282 | if user.is_authenticated(): |
|---|
| 283 | selected_theme = user.forum_profile.theme |
|---|
| 284 | theme_style = '<link rel="stylesheet" type="text/css" href="%(media_url)sforum/themes/%(theme)s/style.css" />' |
|---|
| 285 | else: |
|---|
| 286 | theme_style = '<link rel="stylesheet" type="text/css" href="%(media_url)sforum/themes/default/style.css" />' |
|---|
| 287 | |
|---|
| 288 | return theme_style % dict( |
|---|
| 289 | media_url=settings.MEDIA_URL, |
|---|
| 290 | theme=selected_theme |
|---|
| 291 | ) |
|---|
| 292 | |
|---|
| 293 | @register.simple_tag |
|---|
| 294 | def set_markup_editor(user, markup=None): |
|---|
| 295 | markup_style = '' |
|---|
| 296 | if user.is_authenticated(): |
|---|
| 297 | markup_style = ''' |
|---|
| 298 | <link rel="stylesheet" type="text/css" href="%(media_url)sforum/js/markitup/skins/markitup/style.css" /> |
|---|
| 299 | <link rel="stylesheet" type="text/css" href="%(media_url)sforum/js/markitup/sets/%(markup)s/style.css" /> |
|---|
| 300 | <script type="text/javascript" src="%(media_url)sforum/js/markitup/jquery.markitup.pack.js"></script> |
|---|
| 301 | <script type="text/javascript" src="%(media_url)sforum/js/markitup/sets/%(markup)s/set.js"></script> |
|---|
| 302 | <script type="text/javascript" src="%(media_url)sforum/js/markup/%(markup)s/board.js"></script> |
|---|
| 303 | ''' % dict( |
|---|
| 304 | media_url=settings.MEDIA_URL, |
|---|
| 305 | markup=markup if markup else user.forum_profile.markup |
|---|
| 306 | ) |
|---|
| 307 | return markup_style |
|---|