]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/templatetags/extra_tags.py
making the get_score_badge method decoratable, creating a private instance of it...
[osqa.git] / forum / templatetags / extra_tags.py
index deb0567ea4db0a4716e38cf1936bc662423d7716..1acb96993cb312500f6ffe16d977e4709d1c6c1d 100644 (file)
@@ -5,9 +5,11 @@ import datetime
 import math
 import re
 import logging
+import random
 from django import template
-from django.utils.encoding import smart_unicode
+from django.utils.encoding import smart_unicode, force_unicode, smart_str
 from django.utils.safestring import mark_safe
+from django.utils import dateformat
 from forum.models import Question, Answer, QuestionRevision, AnswerRevision, NodeRevision
 from django.utils.translation import ugettext as _
 from django.utils.translation import ungettext
@@ -22,7 +24,7 @@ from django.core.urlresolvers import reverse
 register = template.Library()
 
 GRAVATAR_TEMPLATE = ('<img class="gravatar" width="%(size)s" height="%(size)s" '
-'src="http://www.gravatar.com/avatar/%(gravatar_hash)s'
+'src="https://secure.gravatar.com/avatar/%(gravatar_hash)s'
 '?s=%(size)s&amp;d=%(default)s&amp;r=%(rating)s" '
 'alt="%(username)s\'s gravatar image" />')
 
@@ -45,6 +47,9 @@ def gravatar(user, size):
 
 @register.simple_tag
 def get_score_badge(user):
+    return _get_score_badge(user)
+
+def _get_score_badge(user):
     if user.is_suspended():
         return _("(suspended)")
 
@@ -77,6 +82,60 @@ def get_score_badge(user):
     'reputationword' : _('reputation points'),
     })
 
+# Usage: {% get_accept_rate node.author %}
+@register.simple_tag
+def get_accept_rate(user):
+    # If the Show Accept Rate feature is not activated this tag should return a blank string
+    if not settings.SHOW_USER_ACCEPT_RATE:
+        return ""
+
+    # Freeze accept rate for users
+    freeze_accept_rate_for_users_users = settings.FREEZE_ACCEPT_RATE_FOR.value
+    if user.username in list(freeze_accept_rate_for_users_users):
+        freeze = True
+    else:
+        freeze = False
+
+    # We get the number of all user's answers.
+    total_answers_count = Answer.objects.filter(author=user).count()
+
+    # We get the number of the user's accepted answers.
+    accepted_answers_count = Answer.objects.filter(author=user, state_string__contains="(accepted)").count()
+
+    # In order to represent the accept rate in percentages we divide the number of the accepted answers to the
+    # total answers count and make a hundred multiplication.
+    try:
+        accept_rate = (float(accepted_answers_count) / float(total_answers_count) * 100)
+    except ZeroDivisionError:
+        accept_rate = 0
+
+    # If the user has more than one accepted answers the rate title will be in plural.
+    if accepted_answers_count > 1:
+        accept_rate_number_title = _('%(user)s has %(count)d accepted answers') % {
+            'user' :  smart_unicode(user.username),
+            'count' : int(accepted_answers_count)
+        }
+    # If the user has one accepted answer we'll be using singular.
+    elif accepted_answers_count == 1:
+        accept_rate_number_title = _('%s has one accepted answer') % smart_unicode(user.username)
+    # This are the only options. Otherwise there are no accepted answers at all.
+    else:
+        if freeze:
+            accept_rate_number_title = ""
+        else:
+            accept_rate_number_title = _('%s has no accepted answers') % smart_unicode(user.username)
+
+    html_output = """
+    <span title="%(accept_rate_title)s" class="accept_rate">%(accept_rate_label)s:</span>
+    <span title="%(accept_rate_number_title)s">%(accept_rate)d&#37;</span>
+    """ % {
+        'accept_rate_label' : _('accept rate'),
+        'accept_rate_title' : _('Rate of the user\'s accepted answers'),
+        'accept_rate' : 100 if freeze else int(accept_rate),
+        'accept_rate_number_title' : u'%s' % accept_rate_number_title,
+    }
+
+    return mark_safe(html_output)
 
 @register.simple_tag
 def get_age(birthday):
@@ -98,11 +157,11 @@ def diff_date(date, limen=2):
     hours = int(diff.seconds/3600)
     minutes = int(diff.seconds/60)
 
-    if days > 2:
-        if date.year == now.year:
-            return date.strftime("%s %s %s %s" % (_("%b"), _("%d"), _("at"), "%H:%M"))
-        else:
-            return date.strftime("%b %d '%y at %H:%M")
+    if date.year != now.year:
+        return dateformat.format(date, 'd M \'y, H:i')
+    elif days > 2:
+        return dateformat.format(date, 'd M, H:i')
+
     elif days == 2:
         return _('2 days ago')
     elif days == 1:
@@ -118,8 +177,33 @@ def diff_date(date, limen=2):
 def media(url):
     url = skins.find_media_source(url)
     if url:
-        url = '///' + settings.FORUM_SCRIPT_ALIAS + '/m/' + url
-        return posixpath.normpath(url)
+        # Create the URL prefix.
+        url_prefix = settings.FORCE_SCRIPT_NAME + '/m/'
+
+        # Make sure any duplicate forward slashes are replaced with a single
+        # forward slash.
+        url_prefix = re.sub("/+", "/", url_prefix)
+
+        url = url_prefix + url
+        return url
+
+@register.simple_tag
+def get_tag_font_size(tag):
+    occurrences_of_current_tag = tag.used_count
+
+    # Occurrences count settings
+    min_occurs = int(settings.TAGS_CLOUD_MIN_OCCURS)
+    max_occurs = int(settings.TAGS_CLOUD_MAX_OCCURS)
+
+    # Font size settings
+    min_font_size = int(settings.TAGS_CLOUD_MIN_FONT_SIZE)
+    max_font_size = int(settings.TAGS_CLOUD_MAX_FONT_SIZE)
+
+    # Calculate the font size of the tag according to the occurrences count
+    weight = (math.log(occurrences_of_current_tag)-math.log(min_occurs))/(math.log(max_occurs)-math.log(min_occurs))
+    font_size_of_current_tag = min_font_size + int(math.floor((max_font_size-min_font_size)*weight))
+
+    return font_size_of_current_tag
 
 class ItemSeparatorNode(template.Node):
     def __init__(self, separator):
@@ -138,7 +222,7 @@ class BlockMediaUrlNode(template.Node):
         self.items = nodelist
 
     def render(self, context):
-        prefix = '///' + settings.FORUM_SCRIPT_ALIAS + 'm/'
+        prefix = settings.APP_URL + 'm/'
         url = ''
         if self.items:
             url += '/'
@@ -147,7 +231,7 @@ class BlockMediaUrlNode(template.Node):
 
         url = skins.find_media_source(url)
         url = prefix + url
-        out = posixpath.normpath(url)
+        out = url
         return out.replace(' ', '')
 
 @register.tag(name='blockmedia')
@@ -167,7 +251,7 @@ def blockmedia(parser, token):
 
 @register.simple_tag
 def fullmedia(url):
-    domain = settings.APP_URL
+    domain = settings.APP_BASE_URL
     #protocol = getattr(settings, "PROTOCOL", "http")
     path = media(url)
     return "%s%s" % (domain, path)
@@ -228,13 +312,17 @@ class DeclareNode(template.Node):
                 d['os'] = os
                 d['html'] = html
                 d['reverse'] = reverse
+                d['settings'] = settings
+                d['smart_str'] = smart_str
+                d['smart_unicode'] = smart_unicode
+                d['force_unicode'] = force_unicode
                 for c in clist:
                     d.update(c)
                 try:
-                    context[m.group(1).strip()] = eval(m.group(3).strip(), d)
+                    command = m.group(3).strip()
+                    context[m.group(1).strip()] = eval(command, d)
                 except Exception, e:
                     logging.error("Error in declare tag, when evaluating: %s" % m.group(3).strip())
-                    raise
         return ''
 
 @register.tag(name='declare')
@@ -242,3 +330,27 @@ def do_declare(parser, token):
     nodelist = parser.parse(('enddeclare',))
     parser.delete_first_token()
     return DeclareNode(nodelist)
+
+# Usage: {% random 1 999 %}
+# Generates random number in the template
+class RandomNumberNode(template.Node):
+    # We get the limiting numbers
+    def __init__(self, int_from, int_to):
+        self.int_from = int(int_from)
+        self.int_to = int(int_to)
+
+    # We generate the random number using the standard python interface
+    def render(self, context):
+        return str(random.randint(self.int_from, self.int_to))
+
+@register.tag(name="random")
+def random_number(parser, token):
+    # Try to get the limiting numbers from the token
+    try:
+        tag_name, int_from, int_to = token.split_contents()
+    except ValueError:
+        # If we had no success -- raise an exception
+        raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]
+
+    # Call the random Node
+    return RandomNumberNode(int_from, int_to)