8 from django import template
9 from django.utils.encoding import smart_unicode
10 from django.utils.safestring import mark_safe
11 from forum.models import Question, Answer, QuestionRevision, AnswerRevision, NodeRevision
12 from django.utils.translation import ugettext as _
13 from django.utils.translation import ungettext
14 from django.utils import simplejson
15 from forum import settings
16 from django.template.defaulttags import url as default_url
17 from forum import skins
18 from forum.utils import html
19 from django.core.urlresolvers import reverse
21 register = template.Library()
23 GRAVATAR_TEMPLATE = ('<img class="gravatar" width="%(size)s" height="%(size)s" '
24 'src="http://www.gravatar.com/avatar/%(gravatar_hash)s'
25 '?s=%(size)s&d=%(default)s&r=%(rating)s" '
26 'alt="%(username)s\'s gravatar image" />')
29 def gravatar(user, size):
31 gravatar = user['gravatar']
32 username = user['username']
33 except (TypeError, AttributeError, KeyError):
34 gravatar = user.gravatar
35 username = user.username
36 return mark_safe(GRAVATAR_TEMPLATE % {
38 'gravatar_hash': gravatar,
39 'default': settings.GRAVATAR_DEFAULT_IMAGE,
40 'rating': settings.GRAVATAR_ALLOWED_RATING,
41 'username': template.defaultfilters.urlencode(username),
46 def get_score_badge(user):
47 if user.is_suspended():
48 return _("(suspended)")
50 BADGE_TEMPLATE = '<span class="score" title="%(reputation)s %(reputationword)s">%(reputation)s</span>'
52 BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(gold)s %(badgesword)s">'
53 '<span class="badge1">●</span>'
54 '<span class="badgecount">%(gold)s</span>'
57 BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(silver)s %(badgesword)s">'
58 '<span class="silver">●</span>'
59 '<span class="badgecount">%(silver)s</span>'
62 BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(bronze)s %(badgesword)s">'
63 '<span class="bronze">●</span>'
64 '<span class="badgecount">%(bronze)s</span>'
66 BADGE_TEMPLATE = smart_unicode(BADGE_TEMPLATE, encoding='utf-8', strings_only=False, errors='strict')
67 return mark_safe(BADGE_TEMPLATE % {
68 'reputation' : user.reputation,
70 'silver' : user.silver,
71 'bronze' : user.bronze,
72 'badgesword' : _('badges'),
73 'reputationword' : _('reputation points'),
78 def get_age(birthday):
79 current_time = datetime.datetime(*time.localtime()[0:6])
81 month = birthday.month
83 diff = current_time - datetime.datetime(year, month, day, 0, 0, 0)
84 return diff.days / 365
87 def diff_date(date, limen=2):
91 now = datetime.datetime.now()
94 hours = int(diff.seconds/3600)
95 minutes = int(diff.seconds/60)
98 if date.year == now.year:
99 return date.strftime("%b %d at %H:%M")
101 return date.strftime("%b %d '%y at %H:%M")
103 return _('2 days ago')
105 return _('yesterday')
107 return ungettext('%(hr)d hour ago', '%(hr)d hours ago', hours) % {'hr':hours}
108 elif diff.seconds >= 60:
109 return ungettext('%(min)d min ago', '%(min)d mins ago', minutes) % {'min':minutes}
111 return ungettext('%(sec)d sec ago', '%(sec)d secs ago', diff.seconds) % {'sec':diff.seconds}
115 url = skins.find_media_source(url)
117 url = '///' + settings.FORUM_SCRIPT_ALIAS + '/m/' + url
118 return posixpath.normpath(url)
120 class ItemSeparatorNode(template.Node):
121 def __init__(self, separator):
122 sep = separator.strip()
123 if sep[0] == sep[-1] and sep[0] in ('\'', '"'):
126 raise template.TemplateSyntaxError('separator in joinitems tag must be quoted')
129 def render(self, context):
132 class BlockMediaUrlNode(template.Node):
133 def __init__(self, nodelist):
134 self.items = nodelist
136 def render(self, context):
137 prefix = '///' + settings.FORUM_SCRIPT_ALIAS + 'm/'
141 for item in self.items:
142 url += item.render(context)
144 url = skins.find_media_source(url)
146 out = posixpath.normpath(url)
147 return out.replace(' ', '')
149 @register.tag(name='blockmedia')
150 def blockmedia(parser, token):
152 tagname = token.split_contents()
154 raise template.TemplateSyntaxError("blockmedia tag does not use arguments")
157 nodelist.append(parser.parse(('endblockmedia')))
158 next = parser.next_token()
159 if next.contents == 'endblockmedia':
161 return BlockMediaUrlNode(nodelist)
166 domain = settings.APP_URL
167 #protocol = getattr(settings, "PROTOCOL", "http")
169 return "%s%s" % (domain, path)
172 class SimpleVarNode(template.Node):
173 def __init__(self, name, value):
175 self.value = template.Variable(value)
177 def render(self, context):
178 context[self.name] = self.value.resolve(context)
181 class BlockVarNode(template.Node):
182 def __init__(self, name, block):
186 def render(self, context):
187 source = self.block.render(context)
188 context[self.name] = source.strip()
192 @register.tag(name='var')
193 def do_var(parser, token):
194 tokens = token.split_contents()[1:]
196 if not len(tokens) or not re.match('^\w+$', tokens[0]):
197 raise template.TemplateSyntaxError("Expected variable name")
200 nodelist = parser.parse(('endvar',))
201 parser.delete_first_token()
202 return BlockVarNode(tokens[0], nodelist)
203 elif len(tokens) == 3:
204 return SimpleVarNode(tokens[0], tokens[2])
206 raise template.TemplateSyntaxError("Invalid number of arguments")
208 class DeclareNode(template.Node):
209 dec_re = re.compile('^\s*(\w+)\s*(:?=)\s*(.*)$')
211 def __init__(self, block):
214 def render(self, context):
215 source = self.block.render(context)
217 for line in source.splitlines():
218 m = self.dec_re.search(line)
220 clist = list(context)
226 d['reverse'] = reverse
230 context[m.group(1).strip()] = eval(m.group(3).strip(), d)
232 logging.error("Error in declare tag, when evaluating: %s" % m.group(3).strip())
236 @register.tag(name='declare')
237 def do_declare(parser, token):
238 nodelist = parser.parse(('enddeclare',))
239 parser.delete_first_token()
240 return DeclareNode(nodelist)