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 extra_filters import decorated_int
20 from django.core.urlresolvers import reverse
22 register = template.Library()
24 GRAVATAR_TEMPLATE = ('<img class="gravatar" width="%(size)s" height="%(size)s" '
25 'src="http://www.gravatar.com/avatar/%(gravatar_hash)s'
26 '?s=%(size)s&d=%(default)s&r=%(rating)s" '
27 'alt="%(username)s\'s gravatar image" />')
30 def gravatar(user, size):
32 gravatar = user['gravatar']
33 username = user['username']
34 except (TypeError, AttributeError, KeyError):
35 gravatar = user.gravatar
36 username = user.username
37 return mark_safe(GRAVATAR_TEMPLATE % {
39 'gravatar_hash': gravatar,
40 'default': settings.GRAVATAR_DEFAULT_IMAGE,
41 'rating': settings.GRAVATAR_ALLOWED_RATING,
42 'username': template.defaultfilters.urlencode(username),
47 def get_score_badge(user):
48 if user.is_suspended():
49 return _("(suspended)")
51 repstr = decorated_int(user.reputation, "")
53 BADGE_TEMPLATE = '<span class="score" title="%(reputation)s %(reputationword)s">%(repstr)s</span>'
55 BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(gold)s %(badgesword)s">'
56 '<span class="badge1">●</span>'
57 '<span class="badgecount">%(gold)s</span>'
60 BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(silver)s %(badgesword)s">'
61 '<span class="silver">●</span>'
62 '<span class="badgecount">%(silver)s</span>'
65 BADGE_TEMPLATE = '%s%s' % (BADGE_TEMPLATE, '<span title="%(bronze)s %(badgesword)s">'
66 '<span class="bronze">●</span>'
67 '<span class="badgecount">%(bronze)s</span>'
69 BADGE_TEMPLATE = smart_unicode(BADGE_TEMPLATE, encoding='utf-8', strings_only=False, errors='strict')
70 return mark_safe(BADGE_TEMPLATE % {
71 'reputation' : user.reputation,
74 'silver' : user.silver,
75 'bronze' : user.bronze,
76 'badgesword' : _('badges'),
77 'reputationword' : _('reputation points'),
82 def get_age(birthday):
83 current_time = datetime.datetime(*time.localtime()[0:6])
85 month = birthday.month
87 diff = current_time - datetime.datetime(year, month, day, 0, 0, 0)
88 return diff.days / 365
91 def diff_date(date, limen=2):
95 now = datetime.datetime.now()
98 hours = int(diff.seconds/3600)
99 minutes = int(diff.seconds/60)
102 if date.year == now.year:
103 return date.strftime(_("%b %d at %H:%M").encode())
105 return date.strftime(_("%b %d '%y at %H:%M").encode())
107 return _('2 days ago')
109 return _('yesterday')
111 return ungettext('%(hr)d ' + _("hour ago"), '%(hr)d ' + _("hours ago"), hours) % {'hr':hours}
112 elif diff.seconds >= 60:
113 return ungettext('%(min)d ' + _("min ago"), '%(min)d ' + _("mins ago"), minutes) % {'min':minutes}
115 return ungettext('%(sec)d ' + _("sec ago"), '%(sec)d ' + _("secs ago"), diff.seconds) % {'sec':diff.seconds}
119 url = skins.find_media_source(url)
121 # Create the URL prefix.
122 url_prefix = settings.FORCE_SCRIPT_NAME + '/m/'
124 # Make sure any duplicate forward slashes are replaced with a single
126 url_prefix = re.sub("/+", "/", url_prefix)
128 url = url_prefix + url
131 class ItemSeparatorNode(template.Node):
132 def __init__(self, separator):
133 sep = separator.strip()
134 if sep[0] == sep[-1] and sep[0] in ('\'', '"'):
137 raise template.TemplateSyntaxError('separator in joinitems tag must be quoted')
140 def render(self, context):
143 class BlockMediaUrlNode(template.Node):
144 def __init__(self, nodelist):
145 self.items = nodelist
147 def render(self, context):
148 prefix = settings.APP_URL + 'm/'
152 for item in self.items:
153 url += item.render(context)
155 url = skins.find_media_source(url)
158 return out.replace(' ', '')
160 @register.tag(name='blockmedia')
161 def blockmedia(parser, token):
163 tagname = token.split_contents()
165 raise template.TemplateSyntaxError("blockmedia tag does not use arguments")
168 nodelist.append(parser.parse(('endblockmedia')))
169 next = parser.next_token()
170 if next.contents == 'endblockmedia':
172 return BlockMediaUrlNode(nodelist)
177 domain = settings.APP_BASE_URL
178 #protocol = getattr(settings, "PROTOCOL", "http")
180 return "%s%s" % (domain, path)
183 class SimpleVarNode(template.Node):
184 def __init__(self, name, value):
186 self.value = template.Variable(value)
188 def render(self, context):
189 context[self.name] = self.value.resolve(context)
192 class BlockVarNode(template.Node):
193 def __init__(self, name, block):
197 def render(self, context):
198 source = self.block.render(context)
199 context[self.name] = source.strip()
203 @register.tag(name='var')
204 def do_var(parser, token):
205 tokens = token.split_contents()[1:]
207 if not len(tokens) or not re.match('^\w+$', tokens[0]):
208 raise template.TemplateSyntaxError("Expected variable name")
211 nodelist = parser.parse(('endvar',))
212 parser.delete_first_token()
213 return BlockVarNode(tokens[0], nodelist)
214 elif len(tokens) == 3:
215 return SimpleVarNode(tokens[0], tokens[2])
217 raise template.TemplateSyntaxError("Invalid number of arguments")
219 class DeclareNode(template.Node):
220 dec_re = re.compile('^\s*(\w+)\s*(:?=)\s*(.*)$')
222 def __init__(self, block):
225 def render(self, context):
226 source = self.block.render(context)
228 for line in source.splitlines():
229 m = self.dec_re.search(line)
231 clist = list(context)
237 d['reverse'] = reverse
241 context[m.group(1).strip()] = eval(m.group(3).strip(), d)
243 logging.error("Error in declare tag, when evaluating: %s" % m.group(3).strip())
247 @register.tag(name='declare')
248 def do_declare(parser, token):
249 nodelist = parser.parse(('enddeclare',))
250 parser.delete_first_token()
251 return DeclareNode(nodelist)