root/discussionplugin/0.11/tracdiscussion/api.py

Revision 3519, 52.0 kB (checked in by Blackhex, 6 months ago)
  • Fixed bug in column sorting direction.
Line 
1 # -*- coding: utf8 -*-
2
3 from datetime import *
4
5 from trac.core import *
6 from trac.mimeview import Context
7 from trac.config import Option
8 from trac.perm import PermissionError
9 from trac.web.chrome import add_stylesheet, add_script, add_ctxtnav
10 from trac.wiki.formatter import format_to_html, format_to_oneliner
11 from trac.util.datefmt import to_timestamp, to_datetime, utc, \
12   format_datetime, pretty_timedelta
13 from trac.util.html import html
14 from trac.util.text import to_unicode
15
16 from genshi.template import TemplateLoader
17
18 from tracdiscussion.notification import *
19
20 class DiscussionApi(Component):
21
22     default_display = Option('discussion', 'default_display', 'tree',
23       'Default display mode of topic message list.')
24     forum_sort = Option('discussion', 'forum_sort', 'id', 'Column by which will' +
25       ' be sorted forum lists. Possible values are: id group name subject' +
26       ' time moderators description topics replies lasttopic lastreply')
27     forum_sort_direction = Option('discussion', 'forum_sort_direction', 'asc',
28       'Direction of forum lists sorting. Possible values are: asc desc.')
29     topic_sort = Option('discussion', 'topic_sort', 'id', 'Column by which will' +
30       ' be sorted topic lists. Possible values are: id forum subject time' +
31       ' author body replies lastreply.')
32     topic_sort_direction = Option('discussion', 'topic_sort_direction', 'asc',
33       'Direction of topic lists sorting. Possible values are: asc desc.')
34
35     # Main request processing function.
36
37     def process_discussion(self, context):
38         # Clear data for next request.
39         self.data = {}
40
41         # Get database access.
42         db = self.env.get_db_cnx()
43         context.cursor = db.cursor()
44
45         # Get request items and modes.
46         group, forum, topic, message = self._get_items(context)
47         modes = self._get_modes(context, group, forum, topic, message)
48         self.log.debug(modes)
49
50         # Determine moderator rights.
51         is_moderator = forum and (context.req.authname in forum['moderators']) \
52           or context.req.perm.has_permission('DISCUSSION_ADMIN')
53
54         # Get session data.
55         context.visited_forums = eval(context.req.session.get('visited-forums')
56           or '{}')
57         context.visited_topics = eval(context.req.session.get('visited-topics')
58           or '{}')
59
60         # Perform mode actions.
61         self._do_action(context, modes, group, forum, topic, message,
62           is_moderator)
63
64         # Update session data.
65         context.req.session['visited-topics'] = to_unicode(context.visited_topics)
66         context.req.session['visited-forums'] = to_unicode(context.visited_forums)
67
68         # Convert group, forum topic and message values for pressentation.
69         if group:
70             group['name'] = format_to_oneliner(self.env, context, group['name'])
71             group['description'] = format_to_oneliner(self.env, context,
72               group['description'])
73         if forum:
74             forum['name'] = format_to_oneliner(self.env, context, forum['name'])
75             forum['subject'] = format_to_oneliner(self.env,context,
76               forum['subject'])
77             forum['description'] = format_to_oneliner(self.env, context,
78               forum['description'])
79             forum['time'] = format_datetime(forum['time'])
80         if topic:
81             topic['subject'] = format_to_oneliner(self.env, context,
82               topic['subject'])
83             topic['body'] = format_to_html(self.env, context, topic['body'])
84             topic['author'] = format_to_oneliner(self.env, context,
85               topic['author'])
86             topic['time'] = format_datetime(topic['time'])
87         if message:
88             message['author'] = format_to_oneliner(self.env, context,
89               message['author'])
90             message['body'] = format_to_html(self.env, context, message['body'])
91             message['time'] = format_datetime(message['time'])
92
93         # Fill up template data structure.
94         self.data['authname'] = context.req.authname
95         self.data['is_moderator'] = is_moderator
96         self.data['group'] = group
97         self.data['forum'] = forum
98         self.data['topic'] = topic
99         self.data['message'] = message
100         self.data['mode'] = modes[-1]
101         self.data['time'] = format_datetime(datetime.now(utc))
102         self.data['realm'] = context.resource.realm
103
104         # Add context navigation.
105         if forum:
106             add_ctxtnav(context.req, 'Forum Index',
107               context.req.href.discussion())
108         if topic:
109             add_ctxtnav(context.req, forum['name'],
110               context.req.href.discussion(forum['id']), forum['name'])
111         if message:
112             add_ctxtnav(context.req, topic['subject'],
113               context.req.href.discussion(forum['id'], topic['id']),
114               topic['subject'])
115
116         # Add CSS styles and scripts.
117         add_stylesheet(context.req, 'common/css/wiki.css')
118         add_stylesheet(context.req, 'discussion/css/discussion.css')
119         add_stylesheet(context.req, 'discussion/css/admin.css')
120         add_script(context.req, 'common/js/trac.js')
121         add_script(context.req, 'common/js/search.js')
122         add_script(context.req, 'common/js/wikitoolbar.js')
123
124         # Commit database changes and return template and data.
125         db.commit()
126         self.env.log.debug(self.data)
127         return modes[-1] + '.html', {'discussion' : self.data}
128
129     def _get_items(self, context):
130         group, forum, topic, message = None, None, None, None
131
132         # Populate active group.
133         if context.req.args.has_key('group'):
134             group_id = int(context.req.args.get('group') or 0)
135             group = self.get_group(context, group_id)
136
137         # Populate active forum.
138         if context.req.args.has_key('forum'):
139             forum_id = int(context.req.args.get('forum') or 0)
140             forum = self.get_forum(context, forum_id)
141
142         # Populate active topic.
143         if context.req.args.has_key('topic'):
144             topic_id = int(context.req.args.get('topic') or 0)
145             topic = self.get_topic(context, topic_id)
146
147         # Populate active topic.
148         if context.req.args.has_key('message'):
149             message_id = int(context.req.args.get('message') or 0)
150             message = self.get_message(context, message_id)
151
152         return group, forum, topic, message
153
154     def _get_modes(self, context, group, forum, topic, message):
155         # Get action.
156         action = context.req.args.get('discussion_action')
157         preview = context.req.args.has_key('preview');
158         submit = context.req.args.has_key('submit');
159         self.log.debug('realm: %s, action: %s, preview: %s, submit: %s' % (
160           context.resource.realm, action, preview, submit))
161
162         # Determine mode.
163         if message:
164             if context.resource.realm == 'discussion-admin':
165                 pass
166             elif context.resource.realm == 'discussion-wiki':
167                 if action == 'add':
168                     return ['message-add', 'wiki-message-list']
169                 elif action == 'quote':
170                     return ['message-quote', 'wiki-message-list']
171                 elif action == 'post-add':
172                     if preview:
173                         return ['wiki-message-list']
174                     else:
175                         return ['message-post-add', 'wiki-message-list']
176                 elif action == 'edit':
177                     return ['message-edit', 'wiki-message-list']
178                 elif action == 'post-edit':
179                     if preview:
180                         return ['wiki-message-list']
181                     else:
182                         return ['message-post-edit', 'wiki-message-list']
183                 elif action == 'delete':
184                     return ['message-delete', 'wiki-message-list']
185                 elif action == 'set-display':
186                     return ['message-set-display', 'wiki-message-list']
187                 else:
188                     return ['wiki-message-list']
189             else:
190                 if action == 'add':
191                     return ['message-add', 'message-list']
192                 elif action == 'quote':
193                     return ['message-quote', 'message-list']
194                 elif action == 'post-add':
195                     if preview:
196                         return ['message-list']
197                     else:
198                         return ['message-post-add', 'message-list']
199                 elif action == 'edit':
200                     return ['message-edit', 'message-list']
201                 elif action == 'post-edit':
202                     if preview:
203                         return ['message-list']
204                     else:
205                         return ['message-post-edit', 'message-list']
206                 elif action == 'delete':
207                     return ['message-delete', 'message-list']
208                 elif action == 'set-display':
209                     return ['message-set-display', 'message-list']
210                 else:
211                     return ['message-list']
212         if topic:
213             if context.resource.realm == 'discussion-admin':
214                 pass
215             elif context.resource.realm == 'discussion-wiki':
216                 if action == 'add':
217                     return ['message-add', 'wiki-message-list']
218                 elif action == 'quote':
219                     return ['topic-quote','wiki-message-list']
220                 elif action == 'post-add':
221                     if preview:
222                         return ['wiki-message-list']
223                     else:
224                         return ['message-post-add', 'wiki-message-list']
225                 elif action == 'edit':
226                     return ['topic-edit', 'wiki-message-list']
227                 elif action == 'post-edit':
228                     if preview:
229                         return ['wiki-message-list']
230                     else:
231                         return ['topic-post-edit', 'wiki-message-list']
232                 elif action == 'set-display':
233                     return ['message-set-display', 'wiki-message-list']
234                 else:
235                     return ['wiki-message-list']
236             else:
237                 if action == 'add':
238                     return ['message-add', 'message-list']
239                 elif action == 'quote':
240                     return ['topic-quote', 'message-list']
241                 elif action == 'post-add':
242                     if preview:
243                         return ['message-list']
244                     else:
245                         return ['message-post-add', 'message-list']
246                 elif action == 'edit':
247                     return ['topic-edit', 'message-list']
248                 elif action == 'post-edit':
249                     if preview:
250                         return ['message-list']
251                     else:
252                         return ['topic-post-edit', 'message-list']
253                 elif action == 'delete':
254                     return ['topic-delete', 'topic-list']
255                 elif action == 'move':
256                     return ['topic-move']
257                 elif action == 'post-move':
258                     return ['topic-post-move', 'topic-list']
259                 elif action == 'set-display':
260                     return ['message-set-display', 'message-list']
261                 else:
262                     return ['message-list']
263         elif forum:
264             if context.resource.realm == 'discussion-admin':
265                 if action == 'post-edit':
266                     return ['forum-post-edit', 'admin-forum-list']
267                 else:
268                     return ['admin-forum-list']
269             elif context.resource.realm == 'discussion-wiki':
270                 return ['wiki-message-list']
271             else:
272                 if action == 'add':
273                     return ['topic-add']
274                 elif action == 'post-add':
275                     if preview:
276                         return ['topic-add']
277                     else:
278                         return ['topic-post-add', 'topic-list']
279                 elif action == 'delete':
280                     return ['forum-delete', 'forum-list']
281                 else:
282                     return ['topic-list']
283         elif group:
284             if context.resource.realm == 'discussion-admin':
285                 if action == 'post-add':
286                     return ['forum-post-add', 'admin-forum-list']
287                 elif action == 'post-edit':
288                     return ['group-post-edit', 'admin-group-list']
289                 elif action == 'delete':
290                     return ['forums-delete', 'admin-forum-list']
291                 else:
292                     if group['id']:
293                         return ['admin-group-list']
294                     else:
295                         return ['admin-forum-list']
296             elif context.resource.realm == 'discussion-wiki':
297                 return ['wiki-message-list']
298             else:
299                 if action == 'post-add':
300                     return ['forum-post-add', 'forum-list']
301                 else:
302                     return ['forum-list']
303         else:
304             if context.resource.realm == 'discussion-admin':
305                 if action == 'post-add':
306                     return ['group-post-add', 'admin-group-list']
307                 elif action == 'delete':
308                     return ['groups-delete', 'admin-group-list']
309                 else:
310                     return ['admin-group-list']
311             elif context.resource.realm == 'discussion-wiki':
312                 return ['wiki-message-list']
313             else:
314                 if action == 'add':
315                     return ['forum-add']
316                 elif action == 'post-add':
317                     return ['forum-post-add', 'forum-list']
318                 else:
319                     return ['forum-list']
320
321     def _do_action(self, context, modes, group, forum, topic, message,
322       is_moderator):
323         for mode in modes:
324             if mode == 'group-list':
325                 context.req.perm.assert_permission('DISCUSSION_VIEW')
326
327                 # Display groups.
328                 self.data['groups'] = self.get_groups(context)
329
330             elif mode == 'admin-group-list':
331                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
332
333                 # Get form values.
334                 order = context.req.args.get('order') or 'id'
335                 direction = context.req.args.get('direction') or 'asc'
336
337                 # Prepare values for edit form.
338                 if group:
339                     self.data['name'] = group['name']
340                     self.data['description'] = group['description']
341
342                 # Display groups.
343                 self.data['order'] = order
344                 self.data['direction'] = direction
345                 self.data['groups'] = self.get_groups(context, order,
346                   direction == 'desc')
347
348             elif mode == 'group-add':
349                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
350
351             elif mode == 'group-post-add':
352                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
353
354                 # Get form values.
355                 new_name = context.req.args.get('name')
356                 new_description = context.req.args.get('description')
357
358                 # Add new group.
359                 self.add_group(context, new_name, new_description)
360
361                 # Redirect request to prevent re-submit.
362                 context.req.redirect(context.req.href.discussion('redirect',
363                   href = context.req.path_info))
364
365             elif mode == 'group-post-edit':
366                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
367
368                 # Get form values.
369                 new_group = int(context.req.args.get('group') or 0)
370                 new_name = context.req.args.get('name')
371                 new_description = context.req.args.get('description')
372
373                 # Edit group.
374                 self.edit_group(context, new_group, new_name, new_description)
375
376                 # Redirect request to prevent re-submit.
377                 context.req.redirect(context.req.href.discussion('redirect',
378                   href = context.req.path_info))
379
380             elif mode == 'group-delete':
381                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
382
383             elif mode == 'groups-delete':
384                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
385
386                 # Get selected groups.
387                 selection = context.req.args.get('selection')
388                 if isinstance(selection, (str, unicode)):
389                     selection = [selection]
390
391                 # Delete selected groups.
392                 if selection:
393                     for group_id in selection:
394                         self.delete_group(context, int(group_id))
395
396                 # Redirect request to prevent re-submit.
397                 context.req.redirect(context.req.href.discussion('redirect',
398                   href = context.req.path_info))
399
400             elif mode == 'forum-list':
401                 context.req.perm.assert_permission('DISCUSSION_VIEW')
402
403                 # Get form values.
404                 order = context.req.args.get('order') or self.forum_sort
405                 direction = context.req.args.get('direction') or \
406                   self.forum_sort_direction
407
408
409                 self.log.debug('direction: %s' % (direction,))
410
411
412                 # Display forums.
413                 self.data['order'] = order
414                 self.data['direction'] = direction
415                 self.data['groups'] = self.get_groups(context)
416                 self.data['forums'] = self.get_forums(context, order,
417                   direction == 'desc')
418                 self.data['forum'] = None
419
420             elif mode == 'admin-forum-list':
421                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
422
423                 # Get ordering arguments values.
424                 order = context.req.args.get('order') or self.forum_sort
425                 direction = context.req.args.get('direction') or \
426                   self.forum_sort_direction
427
428                 # Prepare values for edit form.
429                 if forum:
430                     self.data['name'] = forum['name']
431                     self.data['subject'] = forum['subject']
432                     self.data['description'] = forum['description']
433                     self.data['moderators'] = forum['moderators']
434                     self.data['group'] = forum['group']
435
436                 # Display forums.
437                 self.data['order'] = order
438                 self.data['direction'] = direction
439                 self.data['users'] = self.get_users(context)
440                 self.data['groups'] = self.get_groups(context)
441                 self.data['forums'] = self.get_forums(context, order,
442                   direction == 'desc')
443
444             elif mode == 'forum-add':
445                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
446
447                 # Display Add Forum form.
448                 self.data['users'] = self.get_users(context)
449                 self.data['groups'] = self.get_groups(context)
450
451             elif mode == 'forum-post-add':
452                 context.req.perm.assert_permission('DISCUSSION_ADMIN')
453
454                 # Get form values
455                 new_name = context.req.args.get('name')
456                 new_author = context.req.authname
457                 new_subject = context.req.args.get('subject')
458                 new_description = context.req.args.get('description')
459                 new_moderators = context.req.args.get('moderators')
460                 new_group = int(context.req.args.get