Changeset 1066

Show
Ignore:
Timestamp:
07/28/06 07:36:21 (2 years ago)
Author:
Blackhex
Message:

DiscussionPlugin:

  • Big code structure rewrite.
  • Qutote functionality for ticket #513
  • Added testing sheet in ODF
  • Few changes when displaying empty lists.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • discussionplugin/0.9/setup.py

    r1009 r1066  
    66setup( 
    77  name = 'TracDiscussion', 
    8   version = '0.4', 
     8  version = '0.5', 
    99  packages = ['tracdiscussion', 'tracdiscussion.db'], 
    1010  package_data = {'tracdiscussion' : ['templates/*.cs', 'htdocs/css/*.css']}, 
  • discussionplugin/0.9/tracdiscussion/admin.py

    r1034 r1066  
    1616    # IAdminPageProvider 
    1717    def get_admin_pages(self, req): 
    18         if req.perm.has_permission('DISCUSSION_MODIFY'): 
     18        if req.perm.has_permission('DISCUSSION_ADMIN'): 
    1919            yield ('discussion', 'Discussion System', 'group', 'Forum Groups') 
    2020            yield ('discussion', 'Discussion System', 'forum', 'Forums') 
    2121 
    2222    def process_admin_request(self, req, category, page, path_info): 
    23         # Check permission 
    24         req.perm.assert_permission('DISCUSSION_MODIFY') 
     23        # Prepare request object 
     24        if page == 'forum': 
     25            if not req.args.has_key('group'): 
     26                req.args['group'] = '-1' 
     27            if path_info: 
     28                req.args['forum'] = path_info 
     29        else: 
     30            if path_info: 
     31                req.args['group'] = path_info 
     32        req.args['component'] = 'admin' 
    2533 
    26         # Get access to database 
    27         db = self.env.get_db_cnx() 
    28         cursor = db.cursor() 
    29  
    30         # CSS styles 
    31         add_stylesheet(req, 'common/css/wiki.css') 
    32         add_stylesheet(req, 'discussion/css/admin.css') 
    33  
    34         # Get action 
    35         action = req.args.get('discussion_action') 
    36         submit = req.args.has_key('submit'); 
    37         cancel = req.args.has_key('cancel'); 
    38  
    39         # Determine mode 
    40         if page == 'group': 
    41             if action == 'post-add': 
    42                 mode = 'group-post-add' 
    43             elif action == 'post-edit': 
    44                 if submit: 
    45                     mode = 'group-post-edit' 
    46                 else: 
    47                     mode = 'group-admin' 
    48             elif action == 'delete': 
    49                 mode = 'group-delete' 
    50             else: 
    51                 mode = 'group-admin' 
    52         elif page == 'forum': 
    53             if action == 'post-add': 
    54                 mode = 'forum-post-add' 
    55             elif action == 'post-edit': 
    56                 if submit: 
    57                     mode = 'forum-post-edit' 
    58                 else: 
    59                     mode = 'forum-admin' 
    60             elif action == 'delete': 
    61                 mode = 'forum-delete' 
    62             else: 
    63                 mode = 'forum-admin' 
    64  
    65         # Perform mode action 
    66         if mode == 'group-admin': 
    67             # Get selected group 
    68             if path_info: 
    69                 req.hdf['discussion.group'] = get_group(cursor, self.env, req, 
    70                   self.log, path_info) 
    71  
    72             # Display group list 
    73             req.hdf['discussion.groups'] = get_groups(cursor, self.env, req, 
    74               self.log) 
    75         elif mode == 'group-post-add': 
    76             # Get form values 
    77             name = Markup(req.args.get('name')) 
    78             description = Markup(req.args.get('description')) 
    79  
    80             # Add new group 
    81             add_group(cursor, self.log, name, description) 
    82  
    83             # Display group list 
    84             req.hdf['discussion.groups'] = get_groups(cursor, self.env, req, 
    85               self.log) 
    86             mode = 'group-admin' 
    87         elif mode == 'group-post-edit': 
    88             # Get form values 
    89             group = req.args.get('group') 
    90             name = Markup(req.args.get('name')) 
    91             description = Markup(req.args.get('description')) 
    92  
    93             # Add new group 
    94             edit_group(cursor, self.log, group, name, description) 
    95  
    96             # Display group list 
    97             req.hdf['discussion.groups'] = get_groups(cursor, self.env, req, 
    98               self.log) 
    99             mode = 'group-admin' 
    100         elif mode == 'group-delete': 
    101             # Get form values 
    102             selection = req.args.get('selection') 
    103             if isinstance(selection, (str, unicode)): 
    104                 selection = [selection] 
    105  
    106             # Delete selected groups 
    107             if selection: 
    108                 for group in selection: 
    109                     delete_group(cursor, self.log, group) 
    110  
    111             # Display group list 
    112             req.hdf['discussion.groups'] = get_groups(cursor, self.env, req, 
    113               self.log) 
    114             mode = 'group-admin' 
    115         elif mode == 'forum-admin': 
    116             # Get selected group 
    117             if path_info: 
    118                 req.hdf['discussion.forum'] = get_forum(cursor, self.env, req, 
    119                   self.log, path_info) 
    120  
    121             # Display forum list 
    122             req.hdf['discussion.forums'] = get_forums(cursor, self.env, req, 
    123               self.log) 
    124             req.hdf['discussion.groups'] = get_groups(cursor, self.env, req, 
    125               self.log) 
    126         elif mode == 'forum-post-add': 
    127             # Get form values 
    128             name = Markup(req.args.get('name')) 
    129             author = req.authname 
    130             subject = Markup(req.args.get('subject')) 
    131             description = Markup(req.args.get('description')) 
    132             moderators = Markup(req.args.get('moderators')) 
    133             group = req.args.get('group') 
    134  
    135             if not moderators: 
    136                 moderators = [] 
    137             if not isinstance(moderators, list): 
    138                 moderators = [moderators] 
    139  
    140             # Add new forum 
    141             add_forum(cursor, self.log, name, author, subject, description, 
    142               moderators, group) 
    143  
    144             # Display forum list 
    145             req.hdf['discussion.forums'] = get_forums(cursor, self.env, req, 
    146               self.log) 
    147             req.hdf['discussion.groups'] = get_groups(cursor, self.env, req, 
    148               self.log) 
    149             mode = 'forum-admin' 
    150         elif mode == 'forum-post-edit': 
    151             # Get form values 
    152             forum = req.args.get('forum') 
    153             name = Markup(req.args.get('name')) 
    154             subject = Markup(req.args.get('subject')) 
    155             description = Markup(req.args.get('description')) 
    156             moderators = Markup(req.args.get('moderators')) 
    157             group = req.args.get('group') 
    158  
    159             if not moderators: 
    160                 moderators = [] 
    161             if not isinstance(moderators, list): 
    162                 moderators = [moderators] 
    163  
    164             # Add new forum 
    165             edit_forum(cursor, self.log, forum, name, subject, description, moderators, group) 
    166  
    167             # Display forum list 
    168             req.hdf['discussion.forums'] = get_forums(cursor, self.env, req, 
    169               self.log) 
    170             req.hdf['discussion.groups'] = get_groups(cursor, self.env, req, 
    171               self.log) 
    172             mode = 'forum-admin' 
    173         elif mode == 'forum-delete': 
    174             # Get form values 
    175             selection = req.args.get('selection') 
    176             if isinstance(selection, (str, unicode)): 
    177                 selection = [selection] 
    178  
    179             # Delete selected forums 
    180             if selection: 
    181                 for forum in selection: 
    182                     delete_forum(cursor, self.log, forum) 
    183  
    184             # Display forum list 
    185             req.hdf['discussion.forums'] = get_forums(cursor, self.env, req, 
    186               self.log) 
    187             req.hdf['discussion.groups'] = get_groups(cursor, self.env, req, 
    188               self.log) 
    189             mode = 'forum-admin' 
    190  
    191         # Fill template values and return mode template 
    192         req.hdf['discussion.href'] = self.env.href.admin(category, page) 
    193         req.hdf['discussion.users'] = get_users(self.env, self.log) 
    194         db.commit() 
    195         return mode + '.cs', None 
     34        # Retrun page content 
     35        api = DiscussionApi(self, req) 
     36        return api.render_discussion() 
  • discussionplugin/0.9/tracdiscussion/api.py

    r1034 r1066  
    11from trac.core import * 
     2from trac.web.chrome import add_stylesheet 
    23from trac.wiki import wiki_to_html, wiki_to_oneliner 
    3 from trac.util import format_datetime, pretty_timedelta, escape, unescape, Markup 
     4from trac.util import format_datetime, pretty_timedelta, escape, unescape, \ 
     5  Markup 
     6from trac.util import Markup, format_datetime 
    47import time 
    58 
    6 # Get one item functions 
    7  
    8 def get_message(cursor, env, req, log, id): 
    9     columns = ('id', 'forum', 'topic', 'replyto', 'time', 'author', 'body') 
    10     sql = "SELECT id, forum, topic, replyto, time, author, body FROM message" \ 
    11       " WHERE id = %s" 
    12     log.debug(sql) 
    13     cursor.execute(sql, (id,)) 
    14     for row in cursor: 
    15         row = dict(zip(columns, row)) 
    16         row['author'] = wiki_to_oneliner(row['author'], env) 
    17         row['body'] = wiki_to_html(row['body'], env, req) 
    18         return row 
    19     return None 
    20  
    21 def get_topic(cursor, env, req, log, id): 
    22     columns = ('id', 'forum', 'time', 'subject', 'body', 'author') 
    23     sql = "SELECT id, forum, time, subject, body, author FROM topic WHERE id =" \ 
    24       " %s" 
    25     log.debug(sql) 
    26     cursor.execute(sql, (id,)) 
    27     for row in cursor: 
    28         row = dict(zip(columns, row)) 
    29         row['author'] = wiki_to_oneliner(row['author'], env) 
    30         row['body'] = wiki_to_html(row['body'], env, req) 
    31         row['time'] = format_datetime(row['time']) 
    32         return row 
    33     return None 
    34  
    35 def get_topic_by_subject(cursor, env, req, log, subject): 
    36     columns = ('id', 'forum', 'time', 'subject', 'body', 'author') 
    37     sql = "SELECT id, forum, time, subject, body, author FROM topic WHERE subject =" \ 
    38       " %s" 
    39     log.debug(sql) 
    40     cursor.execute(sql, (subject,)) 
    41     for row in cursor: 
    42         row = dict(zip(columns, row)) 
    43         row['author'] = wiki_to_oneliner(row['author'], env) 
    44         row['body'] = wiki_to_html(row['body'], env, req) 
    45         row['time'] = format_datetime(row['time']) 
    46         return row 
    47     return None 
    48  
    49 def get_forum(cursor, env, req, log, id): 
    50     columns = ('name', 'moderators', 'id', 'time', 'subject', 'description', 
    51       'group') 
    52     sql = "SELECT name, moderators, id, time, subject, description, forum_group" \ 
    53       " FROM forum WHERE id = %s" 
    54     log.debug(sql) 
    55     cursor.execute(sql, (id,)) 
    56     for row in cursor: 
    57         row = dict(zip(columns, row)) 
    58         row['moderators'] = row['moderators'].split(' ') 
    59         row['description'] = wiki_to_oneliner(row['description'], env) 
    60         return row 
    61     return None 
    62  
    63 def get_group(cursor, env, req, log, id): 
    64     columns = ('id', 'name', 'description') 
    65     sql = "SELECT id, name, description FROM forum_group WHERE id = %s" 
    66     log.debug(sql) 
    67     cursor.execute(sql, (id,)) 
    68     for row in cursor: 
    69         row = dict(zip(columns, row)) 
    70         row['name'] = wiki_to_oneliner(row['name'], env) 
    71         row['description'] = wiki_to_oneliner(row['description'], env) 
    72         return row 
    73     return None 
    74  
    75 # Set item functions 
    76  
    77 def set_group(cursor, log, forum, group): 
    78     if not group: 
    79         group = '0' 
    80     sql = "UPDATE forum SET forum_group = %s WHERE id = %s" 
    81     log.debug(sql) 
    82     cursor.execute(sql, (group, forum)) 
    83  
    84 def set_forum(cursor, log, topic, forum): 
    85     sql = "UPDATE topic SET forum = %s WHERE id = %s" 
    86     log.debug(sql) 
    87     cursor.execute(sql, (forum, topic)) 
    88     sql = "UPDATE message SET forum = %s WHERE topic = %s" 
    89     log.debug(sql) 
    90     cursor.execute(sql, (forum, topic)) 
    91  
    92 # Edit all functons 
    93 def edit_group(cursor, log, group, name, description): 
    94     sql = "UPDATE forum_group SET name = %s, description = %s WHERE id = %s" 
    95     log.debug(sql) 
    96     cursor.execute(sql, (name, description, group)) 
    97  
    98 def edit_forum(cursor, log, forum, name, subject, description, moderators, group): 
    99     moderators = ' '.join(moderators) 
    100     if not group: 
    101         group = '0' 
    102     sql = "UPDATE forum SET name = %s, subject = %s, description = %s," \ 
    103       " moderators = %s, forum_group = %s WHERE id = %s" 
    104     log.debug(sql) 
    105     cursor.execute(sql, (name, subject, description, moderators, group, forum)) 
    106  
    107 # Get list functions 
    108  
    109 def get_groups(cursor, env, req, log): 
    110     # Get count of forums without group 
    111     sql = "SELECT COUNT(id) FROM forum WHERE forum_group = 0" 
    112     log.debug(sql) 
    113     cursor.execute(sql) 
    114     no_group_forums = 0 
    115     for row in cursor: 
    116        no_group_forums = row[0] 
    117     groups = [{'id' : 0, 'name' : 'None', 'description' : 'No Group', 
    118       'forums' : no_group_forums}] 
    119  
    120     # Get forum groups 
    121     columns = ('id', 'name', 'description', 'forums') 
    122     sql = "SELECT id, name, description, (SELECT COUNT(id) FROM forum f WHERE" \ 
    123       " f.forum_group = forum_group.id) FROM forum_group" 
    124     log.debug(sql) 
    125     cursor.execute(sql) 
    126     for row in cursor: 
    127         row = dict(zip(columns, row)) 
    128         row['name'] = wiki_to_oneliner(row['name'], env) 
    129         row['description'] = wiki_to_oneliner(row['description'], env) 
    130         groups.append(row) 
    131     return groups 
    132  
    133 def get_forums(cursor, env, req, log): 
    134     columns = ('id', 'name', 'author', 'time', 'moderators', 'group', 'subject', 
    135       'description', 'topics', 'replies', 'lastreply', 'lasttopic') 
    136     sql = "SELECT id, name, author, time, moderators, forum_group, subject," \ 
    137       " description, (SELECT COUNT(id) FROM topic t WHERE t.forum = forum.id)," \ 
    138       " (SELECT COUNT(id) FROM message m WHERE m.forum = forum.id), (SELECT" \ 
    139       " MAX(time) FROM message m WHERE m.forum = forum.id), (SELECT MAX(time)" \ 
    140       " FROM topic t WHERE t.forum = forum.id) FROM forum ORDER BY subject" 
    141     log.debug(sql) 
    142     cursor.execute(sql) 
    143     forums = [] 
    144     for row in cursor: 
    145         row = dict(zip(columns, row)) 
    146         #row['name'] = wiki_to_oneliner(row['name'], env) 
    147         #row['subject'] = wiki_to_oneliner(row['subject'], env) 
    148         row['moderators'] = wiki_to_oneliner(row['moderators'], env) 
    149         row['description'] = wiki_to_oneliner(row['description'], env) 
    150         if row['lastreply']: 
    151             row['lastreply'] = pretty_timedelta(row['lastreply']) 
     9class DiscussionApi(object): 
     10    def __init__(self, component, req): 
     11        self.env = component.env 
     12        self.log = component.log 
     13        self.req = req 
     14        self.db = self.env.get_db_cnx() 
     15        self.cursor = self.db.cursor() 
     16 
     17    # Main request processing function 
     18 
     19    def render_discussion(self): 
     20        # Get request mode 
     21        group, forum, topic, message = self._get_items() 
     22        modes = self._get_modes(group, forum, topic, message) 
     23 
     24        # Determine moderator rights. 
     25        if forum: 
     26            is_moderator = (self.req.authname in forum['moderators']) or \ 
     27              self.req.perm.has_permission('DISCUSSION_ADMIN') 
    15228        else: 
    153             row['lastreply'] = 'No replies' 
    154         if row['lasttopic']: 
    155             row['lasttopic'] = pretty_timedelta(row['lasttopic']) 
     29            is_moderator = self.req.perm.has_permission('DISCUSSION_ADMIN') 
     30 
     31        # Perform mode actions 
     32        self._do_action(modes, group, forum, topic, message, is_moderator) 
     33 
     34        # Add CSS styles 
     35        add_stylesheet(self.req, 'common/css/wiki.css') 
     36        add_stylesheet(self.req, 'discussion/css/discussion.css') 
     37        add_stylesheet(self.req, 'discussion/css/admin.css') 
     38 
     39        # Fill up HDF structure and return template 
     40        self.log.debug('modes: %s' % modes) 
     41        self.req.hdf['discussion.authname'] = self.req.authname 
     42        self.req.hdf['discussion.is_moderator'] = is_moderator 
     43        self.req.hdf['discussion.group'] = group 
     44        self.req.hdf['discussion.forum'] = forum 
     45        self.req.hdf['discussion.topic'] = topic 
     46        self.req.hdf['discussion.message'] = message 
     47        self.req.hdf['discussion.mode'] = modes[-1] 
     48 
     49        # Will be removed after template rename 
     50        if modes[-1] == 'admin-forum-list': 
     51            modes[-1] = 'forum-admin' 
     52        if modes[-1] == 'admin-group-list': 
     53            modes[-1] = 'group-admin' 
     54 
     55        self.db.commit() 
     56        return modes[-1] + '.cs', None 
     57 
     58    def _get_items(self): 
     59        group, forum, topic, message = None, None, None, None 
     60 
     61        # Populate active group 
     62        if self.req.args.has_key('group'): 
     63            group_id = self.req.args.get('group') 
     64            group = self.get_group(group_id) 
     65 
     66        # Populate active forum 
     67        if self.req.args.has_key('forum'): 
     68            forum_id = self.req.args.get('forum') 
     69            forum = self.get_forum(forum_id) 
     70 
     71        # Populate active topic 
     72        if self.req.args.has_key('topic'): 
     73            topic_id = self.req.args.get('topic') 
     74            topic = self.get_topic(topic_id) 
     75 
     76        # Populate active topic 
     77        if self.req.args.has_key('message'): 
     78            message_id = self.req.args.get('message') 
     79            message = self.get_message(message_id) 
     80 
     81        self.log.debug('message: %s' % message) 
     82        self.log.debug('topic: %s' % topic) 
     83        self.log.debug('forum: %s' % forum) 
     84        self.log.debug('group: %s' % group) 
     85        return group, forum, topic, message 
     86 
     87    def _get_modes(self, group, forum, topic, message): 
     88        # Get action 
     89        component = self.req.args.get('component') 
     90        action = self.req.args.get('discussion_action') 
     91        preview = self.req.args.has_key('preview'); 
     92        submit = self.req.args.has_key('submit'); 
     93        self.log.debug('component: %s' % component) 
     94        self.log.debug('action: %s' % action) 
     95 
     96        if component == 'admin': 
     97            self.req.hdf['discussion.href'] = self.env.href.admin('discussion') 
     98        elif component == 'wiki': 
     99            self.req.hdf['discussion.href'] = self.env.href(self.req.path_info) 
    156100        else: 
    157             row['lasttopic'] = 'No topics' 
    158         row['time'] = format_datetime(row['time']) 
    159         forums.append(row) 
    160     return forums 
    161  
    162 def get_topics(cursor, env, req, log, forum): 
    163     columns = ('id', 'forum', 'time', 'subject', 'body', 'author', 
    164       'replies', 'lastreply') 
    165     sql = "SELECT id, forum, time, subject, body, author, (SELECT COUNT(id)" \ 
    166       " FROM message m WHERE m.topic = topic.id), (SELECT MAX(time) FROM" \ 
    167       " message m WHERE m.topic = topic.id) FROM topic WHERE forum = %s ORDER" \ 
    168       " BY time" 
    169     log.debug(sql) 
    170     cursor.execute(sql, (forum,)) 
    171     topics = [] 
    172     for row in cursor: 
    173         row = dict(zip(columns, row)) 
    174         row['author'] = wiki_to_oneliner(row['author'], env) 
    175         row['body'] = wiki_to_html(row['body'], env, req) 
    176         if row['lastreply']: 
    177             row['lastreply'] = pretty_timedelta(row['lastreply']) 
     101            self.req.hdf['discussion.href'] = self.env.href.discussion() 
     102        self.req.hdf['discussion.component'] = component 
     103 
     104        # Determine mode 
     105        if message: 
     106            if component == 'admin': 
     107                pass 
     108            elif component == 'wiki': 
     109                if action == 'add': 
     110                    return ['message-list'] 
     111                elif action == 'quote': 
     112                    return ['message-quote', 'message-list'] 
     113                elif action == 'post-add': 
     114                    if preview: 
     115                        return ['message-list'] 
     116                    else: 
     117                        return ['message-post-add', 'message-list'] 
     118                elif action == 'delete': 
     119                    return ['message-delete', 'message-list'] 
     120                else: 
     121                    return ['message-list'] 
     122            else: 
     123                if action == 'add': 
     124                    return ['message-list'] 
     125                elif action == 'quote': 
     126                    return ['message-quote', 'message-list'] 
     127                elif action == 'post-add': 
     128                    if preview: 
     129                        return ['message-list'] 
     130                    else: 
     131                        return ['message-post-add', 'message-list'] 
     132                elif action == 'delete': 
     133                    return ['message-delete', 'message-list'] 
     134                else: 
     135                    return ['message-list'] 
     136        if topic: 
     137            if component == 'admin': 
     138                pass 
     139            elif component == 'wiki': 
     140                if action == 'add': 
     141                    return ['message-list'] 
     142                elif action == 'quote': 
     143                    return ['message-quote', 'message-list'] 
     144                elif action == 'post-add': 
     145                    if preview: 
     146                        return ['message-list'] 
     147                    else: 
     148                        return ['message-post-add', 'message-list'] 
     149                elif action == 'delete': 
     150                    self.req.hdf['discussion.no_display'] = True 
     151                    return ['topic-delete', 'message-list'] 
     152                else: 
     153                    return ['message-list'] 
     154            else: 
     155                if action == 'add': 
     156                    return ['message-list'] 
     157                elif action == 'quote': 
     158                    return ['message-quote', 'message-list'] 
     159                elif action == 'post-add': 
     160                    if preview: 
     161                        return ['message-list'] 
     162                    else: 
     163                        return ['message-post-add', 'message-list'] 
     164                elif action == 'delete': 
     165                    return ['topic-delete', 'topic-list'] 
     166                elif action == 'move': 
     167                    return ['topic-move'] 
     168                elif action == 'post-move': 
     169                    return ['topic-post-move', 'topic-list'] 
     170                else: 
     171                    return ['message-list'] 
     172        elif forum: 
     173            if component == 'admin': 
     174                if action == 'post-edit': 
     175                    return ['forum-post-edit', 'admin-forum-list'] 
     176                else: 
     177                    return ['admin-forum-list'] 
     178            elif component == 'wiki': 
     179                pass 
     180            else: 
     181                if action == 'add': 
     182                    return ['topic-add'] 
     183                elif action == 'post-add': 
     184                    if preview: 
     185                        return ['topic-add'] 
     186                    else: 
     187                        return ['topic-post-add', 'topic-list'] 
     188                elif action == 'delete': 
     189                    return ['forum-delete', 'forum-list'] 
     190                else: 
     191                    return ['topic-list'] 
     192        elif group: 
     193            if component == 'admin': 
     194                if action == 'post-add': 
     195                    return ['forum-post-add', 'admin-forum-list'] 
     196                elif action == 'post-edit': 
     197                    return ['group-post-edit', 'admin-group-list'] 
     198                elif action == 'delete': 
     199                    return ['forums-delete', 'admin-forum-list'] 
     200                else: 
     201                    if group['id']: 
     202                        return ['admin-group-list'] 
     203                    else: 
     204                        return ['admin-forum-list'] 
     205            elif component == 'wiki': 
     206                pass 
     207            else: 
     208                if action == 'post-add': 
     209                    return ['forum-post-add', 'forum-list'] 
     210                else: 
     211                    return ['forum-list'] 
    178212        else: 
    179             row['lastreply'] = 'No replies' 
    180         row['time'] = format_datetime(row['time']) 
    181         topics.append(row) 
    182     return topics 
    183  
    184 def get_messages(cursor, env, req, log, topic): 
    185     columns = ('id', 'replyto', 'time', 'author', 'body') 
    186     sql = "SELECT id, replyto, time, author, body FROM message WHERE topic =" \ 
    187       " %s ORDER BY time" 
    188     log.debug(sql) 
    189     cursor.execute(sql, (topic,)) 
    190  
    191     messagemap = {} 
    192     messages = [] 
    193  
    194     for row in cursor: 
    195         row = dict(zip(columns, row)) 
    196         row['author'] = wiki_to_oneliner(row['author'], env) 
    197         row['body'] = wiki_to_html(row['body'], env, req) 
    198         row['time'] = format_datetime(row['time']) 
    199         messagemap[row['id']] = row 
    200  
    201         # Add top-level messages to the main list, in order of time 
    202         if row['replyto'] == -1: 
    203             messages.append(row) 
    204  
    205     # Second pass, add replies 
    206     for message in messagemap.values(): 
    207         if message['replyto'] != -1: 
    208             parent = messagemap[message['replyto']] 
    209             if 'replies' in parent: 
    210                 parent['replies'].append(message) 
    211             else: 
    212                 parent['replies'] = [message] 
    213     return messages; 
    214  
    215 def get_users(env, log): 
    216     users = [] 
    217     for user in env.get_known_users(): 
    218         users.append(user[0]) 
    219     return users 
    220  
    221 # Add items functions 
    222  
    223 def add_group(cursor, log, name, description): 
    224     sql = "INSERT INTO forum_group (name, description) VALUES (%s, %s)" 
    225     log.debug(sql) 
    226     cursor.execute(sql, (escape(name), escape(description))) 
    227  
    228  
    229 def add_forum(cursor, log, name, author, subject, description, moderators, 
    230   group): 
    231     moderators = ' '.join(moderators) 
    232     if not group: 
    233         group = '0' 
    234     sql = "INSERT INTO forum (name, author, time, moderators, subject," \ 
    235       " description, forum_group) VALUES (%s, %s, %s, %s, %s, %s, %s)" 
    236     log.debug(sql) 
    237     cursor.execute(sql, (escape(name), escape(author), str(int(time.time())), 
    238       escape(moderators), escape(subject), escape(description), group)) 
    239  
    240 def add_topic(cursor, log, forum, subject, author, body): 
    241     sql = "INSERT INTO topic (forum, time, author, subject, body) VALUES" \ 
    242       " (%s, %s, %s, %s, %s)" 
    243     log.debug(sql) 
    244     cursor.execute(sql, (forum, int(time.time()), escape(author), 
    245       escape(subject), escape(body))) 
    246  
    247 def add_message(cursor, log, forum, topic, replyto, author, body): 
    248     sql = "INSERT INTO message (forum, topic, replyto, time, author, body)" \ 
    249       " VALUES (%s, %s, %s, %s, %s, %s)" 
    250     log.debug(sql) 
    251     log.debug(body) 
    252     cursor.execute(sql, (forum, topic, replyto, int(time.time()), 
    253       escape(author), escape(Markup(body)))) 
    254  
    255 # Delete items functions 
    256  
    257 def delete_group(cursor, log, group): 
    258     sql = "DELETE FROM forum_group WHERE id = %s" 
    259     log.debug(sql) 
    260     cursor.execute(sql, (group,)) 
    261     sql = "UPDATE forum SET forum_group = 0 WHERE forum_group = %s" 
    262     log.debug(sql) 
    263     cursor.execute(sql, (group,)) 
    264  
    265 def delete_forum(cursor, log, forum): 
    266     sql = "DELETE FROM message WHERE forum = %s" 
    267     log.debug(sql) 
    268     cursor.execute(sql, (forum,)) 
    269     sql = "DELETE FROM topic WHERE forum = %s" 
    270     log.debug(sql) 
    271     cursor.execute(sql, (forum,)) 
    272     sql = "DELETE FROM forum WHERE id = %s" 
    273     log.debug(sql) 
    274     cursor.execute(sql, (forum,)) 
    275  
    276 def delete_topic(cursor, log, topic): 
    277     sql = "DELETE FROM message WHERE topic = %s" 
    278     log.debug(sql) 
    279     cursor.execute(sql, (topic,)) 
    280     sql = "DELETE FROM topic WHERE id = %s" 
    281     log.debug(sql) 
    282     cursor.execute(sql, (topic,)) 
    283  
    284 def delete_message(cursor, log, message): 
    285     # Get message replies 
    286     sql = "SELECT id FROM message WHERE replyto = %s" 
    287     log.debug(sql) 
    288     cursor.execute(sql, (message,)) 
    289     replies = [] 
    290     for row in cursor: 
    291         replies.append(row[0]) 
    292  
    293     # Delete all replies 
    294     for reply in replies: 
    295         delete_message(cursor, log, reply) 
    296  
    297     # Delete message itself 
    298     sql = "DELETE FROM message WHERE id = %s" 
    299     log.debug(sql) 
    300     cursor.execute(sql, (message,)) 
     213            if component == 'admin': 
     214                if action == 'post-add': 
     215                    return ['group-post-add', 'admin-group-list'] 
     216                elif action == 'delete': 
     217                    return ['groups-delete', 'admin-group-list'] 
     218                else: 
     219                    return ['admin-group-list'] 
     220            elif component == 'wiki': 
     221                pass 
     222            else: 
     223                if action == 'add': 
     224                    return ['forum-add'] 
     225                elif action == 'post-add': 
     226                    return ['forum-post-add', 'forum-list'] 
     227                else: 
     228                    return ['forum-list'] 
     229 
     230    def _do_action(self, modes, group, forum, topic, message, is_moderator): 
     231        for mode in modes: 
     232            if mode == 'group-list': 
     233                self.req.perm.assert_permission('DISCUSSION_VIEW') 
     234                self.req.hdf['discussion.groups'] = self.get_groups() 
     235            elif mode == 'admin-group-list': 
     236                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     237                self.req.hdf['discussion.groups'] = self.get_groups() 
     238            elif mode == 'group-add': 
     239                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     240            elif mode == 'group-post-add': 
     241                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     242                name = Markup(self.req.args.get('name')) 
     243                description = Markup(self.req.args.get('description')) 
     244                self.add_group(name, description) 
     245            elif mode == 'group-post-edit': 
     246                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     247                group = self.req.args.get('group') 
     248                name = Markup(self.req.args.get('name')) 
     249                description = Markup(self.req.args.get('description')) 
     250                self.edit_group(group, name, description) 
     251            elif mode == 'group-delete': 
     252                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     253            elif mode == 'groups-delete': 
     254                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     255                selection = self.req.args.get('selection') 
     256                if isinstance(selection, (str, unicode)): 
     257                    selection = [selection] 
     258                if selection: 
     259                    for group in selection: 
     260                        self.delete_group(group) 
     261            elif mode == 'forum-list': 
     262                self.req.perm.assert_permission('DISCUSSION_VIEW') 
     263                self.req.hdf['discussion.groups'] = self.get_groups() 
     264                self.req.hdf['discussion.forums'] = self.get_forums() 
     265            elif mode == 'admin-forum-list': 
     266                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     267                self.req.hdf['discussion.users'] = self.get_users() 
     268                self.req.hdf['discussion.groups'] = self.get_groups() 
     269                self.req.hdf['discussion.forums'] = self.get_forums() 
     270            elif mode == 'forum-add': 
     271                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     272                self.req.hdf['discussion.users'] = self.get_users() 
     273                self.req.hdf['discussion.groups'] = self.get_groups() 
     274            elif mode == 'forum-post-add': 
     275                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     276                name = Markup(self.req.args.get('name')) 
     277                author = self.req.authname 
     278                subject = Markup(self.req.args.get('subject')) 
     279                description = Markup(self.req.args.get('description')) 
     280                moderators = self.req.args.get('moderators') 
     281                group = self.req.args.get('group') 
     282                if not moderators: 
     283                    moderators = [] 
     284                if not isinstance(moderators, list): 
     285                     moderators = [moderators] 
     286                self.add_forum(name, author, subject, description, moderators, 
     287                  group) 
     288            elif mode == 'forum-post-edit': 
     289                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     290                forum = self.req.args.get('forum') 
     291                name = Markup(self.req.args.get('name')) 
     292                subject = Markup(self.req.args.get('subject')) 
     293                description = Markup(self.req.args.get('description')) 
     294                moderators = self.req.args.get('moderators') 
     295                group = self.req.args.get('group') 
     296                if not moderators: 
     297                    moderators = [] 
     298                if not isinstance(moderators, list): 
     299                    moderators = [moderators] 
     300                self.edit_forum(forum, name, subject, description, moderators, 
     301                  group) 
     302            elif mode == 'forum-delete': 
     303                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     304                self.delete_forum(forum['id']) 
     305            elif mode == 'forums-delete': 
     306                self.req.perm.assert_permission('DISCUSSION_ADMIN') 
     307                selection = self.req.args.get('selection') 
     308                if isinstance(selection, (str, unicode)): 
     309                    selection = [selection] 
     310                if selection: 
     311                    for forum in selection: 
     312                        self.delete_forum(forum) 
     313            elif mode == 'topic-list': 
     314                self.req.perm.assert_permission('DISCUSSION_VIEW') 
     315                self.req.hdf['discussion.topics'] = self.get_topics(forum['id']) 
     316            elif mode == 'topic-add': 
     317                self.req.perm.assert_permission('DISCUSSION_APPEND') 
     318                author = Markup(self.req.args.get('author')) 
     319                body = Markup(self.req.args.get('body')) 
     320                if author: 
     321                    self.req.hdf['discussion.author'] = wiki_to_oneliner(author, 
     322                      self.env) 
     323                if body: 
     324                    self.req.hdf['discussion.body'] = wiki_to_html(body, 
     325                      self.env, self.req) 
     326                self.req.hdf['discussion.time'] = format_datetime(time.time()) 
     327            elif mode == 'topic-post-add': 
     328                self.req.perm.assert_permission('DISCUSSION_APPEND') 
     329                subject = Markup(self.req.args.get('subject')) 
     330                author = Markup(self.req.args.get('author')) 
     331                body = Markup(self.req.args.get('body')) 
     332                self.add_topic(forum['id'], subject, author, body) 
     333            elif mode == 'topic-move': 
     334                self.req.perm.assert_permission('DISCUSSION_MODERATE') 
     335                if not is_moderator: 
     336                    raise PermissionError('Forum moderate') 
     337                self.req.hdf['discussion.forums'] = self.get_forums() 
     338            elif mode == 'topic-post-move': 
     339                self.req.perm.assert_permission('DISCUSSION_MODERATE') 
     340                if not is_moderator: 
     341                    raise PermissionError('Forum moderate') 
     342                new_forum = self.req.args.get('new_forum') 
     343                self.set_forum(topic['id'], new_forum) 
     344            elif mode == 'topic-delete': 
     345                self.req.perm.assert_permission('DISCUSSION_MODERATE') 
     346                if not is_moderator: 
     347                    raise PermissionError('Forum moderate') 
     348                self.delete_topic(topic['id']) 
     349            elif mode == 'message-list': 
     350                self.req.perm.assert_permission('DISCUSSION_VIEW') 
     351                author = Markup(self.req.args.get('author')) 
     352                body = Markup(self.req.args.get('body')) 
     353                if author: 
     354                    self.req.hdf['discussion.author'] = wiki_to_oneliner(author, 
     355                      self.env) 
     356                if body: 
     357                    self.req.hdf['discussion.body'] = wiki_to_html(body, 
     358                      self.env, self.req) 
     359                self.req.hdf['discussion.time'] = format_datetime(time.time()) 
     360                self.req.hdf['discussion.messages'] = self.get_messages(topic['id']) 
     361            elif mode == 'message-quote': 
     362                self.req.perm.assert_permission('DISCUSSION_APPEND') 
     363                lines = message['body'].splitlines() 
     364                for I in xrange(len(lines)): 
     365                    lines[I] = '> %s' % (lines[I]) 
     366                self.req.hdf['args.body'] = '\n'.join(lines) 
     367            elif mode == 'message-post-add': 
     368                self.req.perm.assert_permission('DISCUSSION_APPEND') 
     369                author = Markup(self.req.args.get('author')) 
     370                body = Markup(self.req.args.get('body')) 
     371                if message: 
     372                    self.add_message(forum['id'], topic['id'], message['id'], 
     373                      author, body) 
     374                else: 
     375                    self.add_message(forum['id'], topic['id'], '-1', author, body) 
     376            elif mode == 'message-delete': 
     377                self.req.perm.assert_permission('DISCUSSION_MODERATE') 
     378                if not is_moderator: 
     379                    raise PermissionError('Forum moderate') 
     380                self.delete_message(message['id']) 
     381 
     382    # Get one item functions 
     383 
     384    def get_message(self, id): 
     385        columns = ('id', 'forum', 'topic', 'replyto', 'time', 'author', 'body') 
     386        sql = "SELECT id, forum, topic, replyto, time, author, body FROM" \ 
     387          " message WHERE id = %s" 
     388        self.log.debug(sql % (id,)) 
     389        self.cursor.execute(sql, (id,)) 
     390        for row in self.cursor: 
     391            row = dict(zip(columns, row)) 
     392            return row 
     393        return None 
     394 
     395    def get_topic(self, id): 
     396        columns = ('id', 'forum', 'time', 'subject', 'body', 'author') 
     397        sql = "SELECT id, forum, time, subject, body, author FROM topic WHERE" \ 
     398          " id = %s" 
     399        self.log.debug(sql % (id,)) 
     400        self.cursor.execute(sql, (id,)) 
     401        for row in self.cursor: 
     402            row = dict(zip(columns, row)) 
     403            row['author'] = wiki_to_oneliner(row['author'], self.env) 
     404            row['body'] = wiki_to_html(row['body'], self.env, self.req) 
     405            row['time'] = format_datetime(row['time']) 
     406            return row 
     407        return None 
     408 
     409    def get_topic_by_subject(self, subject): 
     410        columns = ('id', 'forum', 'time', 'subject', 'body', 'author') 
     411        sql = "SELECT id, forum, time, subject, body, author FROM topic WHERE" \ 
     412          " subject = '%s'" % (subject) 
     413        self.log.debug(sql) 
     414        self.cursor.execute(sql) 
     415        for row in self.cursor: 
     416            row = dict(zip(columns, row)) 
     417            row['author'] = wiki_to_oneliner(row['author'], self.env) 
     418            row['body'] = wiki_to_html(row['body'], self.env, self.req) 
     419            row['time'] = format_datetime(row['time']) 
     420            return row 
     421        return None 
     422 
     423    def get_forum(self, id): 
     424        columns = ('name', 'moderators', 'id', 'time', 'subject', 
     425          'description', 'group') 
     426        sql = "SELECT name, moderators, id, time, subject, description," \ 
     427          " forum_group FROM forum WHERE id = %s" 
     428        self.log.debug(sql % (id,)) 
     429        self.cursor.execute(sql, (id,)) 
     430        for row in self.cursor: 
     431            row = dict(zip(columns, row))