]> git.openstreetmap.org Git - osqa.git/blob - forum/templatetags/node_tags.py
Remove footer link to squatted domain
[osqa.git] / forum / templatetags / node_tags.py
1 from datetime import datetime, timedelta
2 import re
3
4 from forum.models import Question, Action
5 from django.template import Template, Context
6 from django.utils.translation import ungettext, ugettext as _
7 from django.utils.html import strip_tags
8 from django.utils.encoding import smart_unicode
9 from django.utils.safestring import mark_safe
10 from django.conf import settings as django_settings
11 from django.core.urlresolvers import reverse
12 from django import template
13 from forum.actions import *
14 from forum import settings
15
16 register = template.Library()
17
18 @register.inclusion_tag('node/vote_buttons.html')
19 def vote_buttons(post, user):
20     context = dict(post=post, user_vote='none')
21
22     if user.is_authenticated():
23         context['user_vote'] = {1: 'up', -1: 'down', None: 'none'}[VoteAction.get_for(user, post)]
24
25     return context
26
27 @register.inclusion_tag('node/accept_button.html')
28 def accept_button(answer, user):
29     if not settings.DISABLE_ACCEPTING_FEATURE:
30         return {
31             'can_accept': user.is_authenticated() and user.can_accept_answer(answer),
32             'answer': answer,
33             'user': user
34         }
35     else:
36         return ''
37
38 @register.inclusion_tag('node/wiki_symbol.html')
39 def wiki_symbol(user, post):
40     context = {
41         'is_wiki': post.nis.wiki,
42         'post_type': post.friendly_name
43     }
44
45     if post.nis.wiki:
46         if user.can_edit_post(post):
47             context['can_edit'] = True
48             context['edit_url'] = reverse('edit_' + post.node_type, kwargs={'id': post.id})
49         context['by'] = post.nstate.wiki.by.username
50         context['at'] = post.nstate.wiki.at
51
52     return context
53
54 @register.inclusion_tag('node/favorite_mark.html')
55 def favorite_mark(question, user):
56     try:
57         FavoriteAction.objects.get(canceled=False, node=question, user=user)
58         favorited = True
59     except:
60         favorited = False
61
62     return {'favorited': favorited, 'favorite_count': question.favorite_count, 'question': question}
63
64 @register.simple_tag
65 def post_classes(post):
66     classes = []
67
68     if post.nis.deleted:
69         classes.append('deleted')
70
71     if post.node_type == "answer":
72         if (not settings.DISABLE_ACCEPTING_FEATURE) and post.nis.accepted:
73             classes.append('accepted-answer')
74
75         if post.author == post.question.author:
76             classes.append('answered-by-owner')
77
78     return " ".join(classes)
79
80 def post_control(text, url, command=False, withprompt=False, confirm=False, title="", copy=False, extra_classes=[]):
81     classes = (command and "ajax-command" or " ") + (withprompt and " withprompt" or " ") + (confirm and " confirm" or " ") + \
82         (copy and " copy" or " ")
83
84     for extra_class in extra_classes:
85         classes += " %s" % extra_class
86
87     return {'text': text, 'url': url, 'classes': classes, 'title': title}
88
89
90 moderation_enabled = False
91 for m in django_settings.MODULE_LIST:
92     if m.__name__.endswith('moderation'):
93         moderation_enabled = True
94
95 @register.inclusion_tag('node/post_controls.html' if not moderation_enabled else "modules/moderation/node/post_controls.html")
96 def post_controls(post, user):
97     controls = []
98     menu = []
99     post_type = post.node_type
100
101     # We show the link tool if the post is an Answer. It is visible to Guests too.
102     if post_type == "answer":
103         # Answer permanent link tool
104         controls.append(post_control(_('permanent link'), reverse('answer_permanent_link', kwargs={'id' : post.id,}),
105                                      title=_("answer permanent link"), command=True, withprompt=True, copy=True))
106
107         # Users should be able to award points for an answer. Users cannot award their own answers
108         if user != post.author and user.is_authenticated() and user.reputation > 1:
109             controls.append(post_control(_("award points"), reverse('award_points', kwargs={'user_id' : post.author.id,
110                                          'answer_id' : post.id}), title=_("award points to %s") % smart_unicode(post.author.username),
111                                          command=True, withprompt=True))
112
113     # The other controls are visible only to authenticated users.
114     if user.is_authenticated():
115         try:
116             edit_url = reverse('edit_' + post_type, kwargs={'id': post.id})
117             if user.can_edit_post(post):
118                 controls.append(post_control(_('edit'), edit_url))
119             elif post_type == 'question' and user.can_retag_questions():
120                 controls.append(post_control(_('retag'), edit_url))
121         except:
122             pass
123
124         if post_type == 'question':
125             if post.nis.closed and user.can_reopen_question(post):
126                 controls.append(post_control(_('reopen'), reverse('reopen', kwargs={'id': post.id}), command=True))
127             elif not post.nis.closed and user.can_close_question(post):
128                 controls.append(post_control(_('close'), reverse('close', kwargs={'id': post.id}), command=True, withprompt=True))
129
130         if user.can_flag_offensive(post):
131             label = _('report')
132             
133             if user.can_view_offensive_flags(post):
134                 label =  "%s (%d)" % (label, post.flag_count)
135
136
137             report_control = post_control(label, reverse('flag_post', kwargs={'id': post.id}),
138                     command=True, withprompt=True,
139                     title=_("report as offensive (i.e containing spam, advertising, malicious text, etc.)"))
140
141             # Depending on the setting choose where to attach the control
142             if settings.REPORT_OFFENSIVE_CONTROL_POSITION.value == "more":
143                 menu.append(report_control)
144             else:
145                 controls.append(report_control)
146
147         if user.can_delete_post(post):
148             if post.nis.deleted:
149                 controls.append(post_control(_('undelete'), reverse('delete_post', kwargs={'id': post.id}),
150                         command=True, confirm=True))
151             else:
152                 controls.append(post_control(_('delete'), reverse('delete_post', kwargs={'id': post.id}),
153                         command=True, confirm=True))
154
155         if user.can_delete_post(post):
156             menu.append(post_control(_('see revisions'),
157                         reverse('revisions',
158                         kwargs={'id': post.id}),
159                         command=False, confirm=False))
160
161         if settings.WIKI_ON:
162             if (not post.nis.wiki) and user.can_wikify(post):
163                 menu.append(post_control(_('mark as community wiki'), reverse('wikify', kwargs={'id': post.id}),
164                             command=True, confirm=True))
165
166             elif post.nis.wiki and user.can_cancel_wiki(post):
167                 menu.append(post_control(_('cancel community wiki'), reverse('wikify', kwargs={'id': post.id}),
168                             command=True, confirm=True))
169
170         if post.node_type == "answer" and user.can_convert_to_comment(post):
171             menu.append(post_control(_('convert to comment'), reverse('convert_to_comment', kwargs={'id': post.id}),
172                         command=True, withprompt=True))
173         
174         if post.node_type == "answer" and user.can_convert_to_question(post):
175             menu.append(post_control(_('convert to question'), reverse('convert_to_question', kwargs={'id': post.id}),
176                         command=False, confirm=True))
177
178         if user.is_superuser or user.is_staff:
179             plain_text = strip_tags(post.html)
180
181             char_count = len(plain_text)
182             fullStr = plain_text + " "
183             left_trimmedStr = re.sub(re.compile(r"^[^\w]+", re.IGNORECASE), "", fullStr)
184             cleanedStr = re.sub(re.compile(r"[^\w]+", re.IGNORECASE), " ", left_trimmedStr)
185             splitString = cleanedStr.split(" ")
186             word_count = len(splitString) - 1
187
188             metrics = mark_safe("<b>%s %s / %s %s</b>" % (char_count, ungettext('character', 'characters', char_count),
189                                         word_count, ungettext('word', 'words', word_count)))
190
191             menu.append(post_control(metrics, "#", command=False, withprompt=False))
192
193     return {'controls': controls, 'menu': menu, 'post': post, 'user': user}
194
195 def _comments(post, user):
196     all_comments = post.comments.filter_state(deleted=False)\
197                                 .order_by('-added_at' if settings.SHOW_LATEST_COMMENTS_FIRST else 'added_at')
198
199     if len(all_comments) <= 5:
200         top_scorers = all_comments
201     else:
202         top_scorers = sorted(all_comments, lambda c1, c2: cmp(c2.score, c1.score))[0:5]
203
204     comments = []
205     showing = 0
206     for c in all_comments:
207         context = {
208             'can_delete': user.can_delete_comment(c),
209             'can_like': user.can_like_comment(c),
210             'can_edit': user.can_edit_comment(c),
211             'can_convert': user.can_convert_comment_to_answer(c)
212         }
213
214         if c in top_scorers or c.is_reply_to(user):
215             context['top_scorer'] = True
216             showing += 1
217         
218         if context['can_like']:
219             context['likes'] = VoteAction.get_for(user, c) == 1
220
221         context['user'] = c.user
222         context['comment'] = c.comment
223         context.update(dict(c.__dict__))
224         comments.append(context)
225
226     # Generate canned comments
227     canned_comments = []
228     for comment in settings.CANNED_COMMENTS:
229         t = Template(smart_unicode(comment))
230         c = Context({
231             'post' : post,
232             'settings' : settings,
233         })
234         canned_comments.append(t.render(c))
235
236     total = len(all_comments)
237     return {
238         'comments': comments,
239         'canned_comments': canned_comments,
240         'post': post,
241         'can_comment': user.can_comment(post),
242         'max_length': settings.FORM_MAX_COMMENT_BODY,
243         'min_length': settings.FORM_MIN_COMMENT_BODY,
244         'show_gravatar': settings.FORM_GRAVATAR_IN_COMMENTS,
245         'showing': showing,
246         'total': total,
247         'more_comments_count' : int(total - showing),
248         'show_latest_comments_first' : settings.SHOW_LATEST_COMMENTS_FIRST,
249         'user': user,
250     }
251
252 @register.inclusion_tag('node/comments.html')
253 def comments(post, user):
254     return _comments(post, user)
255
256 @register.inclusion_tag("node/contributors_info.html", takes_context=True)
257 def contributors_info(context, node, verb=None):
258     return {
259         'node_verb': verb and verb or ((node.node_type == "question") and _("asked") or (
260                     (node.node_type == "answer") and _("answered") or _("posted"))),
261         'node': node,
262         'context' : context
263     }
264
265 @register.inclusion_tag("node/reviser_info.html")
266 def reviser_info(revision):
267     return {'revision': revision}