Changeset 3517

Show
Ignore:
Timestamp:
04/16/08 01:38:32 (3 months ago)
Author:
Blackhex
Message:
  • Trunk branch for unfinished refactoring created.
  • Fixed #2563.
  • Fixed commas in link titles for 0.11 branch.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • discussionplugin/0.11/tracdiscussion/timeline.py

    r3160 r3517  
    5757            # Get message events 
    5858            for message in self._get_changed_messages(context, start, stop): 
    59                 title = 'New repy on %s created' % (message['forum_name']) 
     59                title = 'New reply on %s created' % (message['forum_name']) 
    6060                description = message['topic_subject'] 
    6161                href = context.req.href.discussion(message['forum'], 
  • discussionplugin/0.11/tracdiscussion/wiki.py

    r2837 r3517  
    111111            self.log.debug(sql % (id,)) 
    112112            cursor.execute(sql, (id,)) 
     113 
     114            # Return link to forum. 
    113115            for row in cursor: 
    114116                row = dict(zip(columns, row)) 
    115                 return html.a(label, href = formatter.href.discussion(id), 
    116                   title = row['subject']) 
    117             return html.a(label, href = '%s/%s' % (formatter.href.discussion(), 
    118               id), title = label, class_ = 'missing') 
     117                href = formatter.href.discussion(id) 
     118                title = row['subject'].replace('"', '') 
     119                return html.a(label, href = href, title = title) 
     120 
     121            # No such forum exists. 
     122            href = formatter.href.discussion(id) 
     123            title = label.replace('"', '') 
     124            return html.a(label, href = href, title = title, class_ = 'missing') 
     125 
    119126        elif ns == 'topic': 
    120127            columns = ('forum', 'forum_subject', 'subject') 
     
    123130            self.log.debug(sql % (id,)) 
    124131            cursor.execute(sql, (id,)) 
     132 
     133            # Return link to topic. 
    125134            for row in cursor: 
    126135                row = dict(zip(columns, row)) 
    127                 return html.a(label, href = '%s#-1' % \ 
    128                   (formatter.href.discussion(row['forum'], id),), title = 
    129                   '%s: %s' % (row['forum_subject'], row['subject'])) 
    130             return html.a(label, href = '%s/%s' % (formatter.href.discussion(), 
    131               id), title = label, class_ = 'missing') 
     136                href = '%s#-1' % (formatter.href.discussion(row['forum'], id)) 
     137                title = ('%s: %s' % (row['forum_subject'], row['subject'])) \ 
     138                  .replace('"', '') 
     139                return html.a(label, href = href, title = title) 
     140 
     141            # No such topic exits. 
     142            href = formatter.href.discussion(id) 
     143            title = label.replace('"', '') 
     144            return html.a(label, href = href, title = title, class_ = 'missing') 
     145 
    132146        elif ns == 'message': 
    133147            columns = ('forum', 'topic', 'forum_subject', 'subject') 
     
    138152            self.log.debug(sql % (id,)) 
    139153            cursor.execute(sql, (id,)) 
     154 
     155            # Return link to message. 
    140156            for row in cursor: 
    141157                row = dict(zip(columns, row)) 
    142                 return html.a(label, href = '%s#%s' % \ 
    143                   (formatter.href.discussion(row['forum'], row['topic'], id), 
    144                   id), title = '%s: %s' % (row['forum_subject'], 
    145                   row['subject'])) 
    146             return html.a(label, href = '%s/%s' % (formatter.href.discussion(), 
    147               id), title = label, class_ = 'missing') 
     158                href = '%s#%s' % (formatter.href.discussion(row['forum'], 
     159                  row['topic'], id), id) 
     160                title = ('%s: %s' % (row['forum_subject'], row['subject'])) \ 
     161                  .replace('"', '') 
     162                return html.a(label, href = href, title = title) 
     163 
     164            # No such message exits. 
     165            href = formatter.href.discussion(id) 
     166            title = label.replace('"', '') 
     167            return html.a(label, href = href, title = title, class_ = 'missing') 
     168 
    148169        else: 
    149             return html.a(label, href = '%s/%s' % (formatter.href.discussion(), 
    150               id), title = label, class_ = 'missing') 
     170            # Unknown namespace. 
     171            href = formatter.href.discussion(id) 
     172            title = label.replace('"', '') 
     173            return html.a(label, href = href, title = title, class_ = 'missing') 
  • discussionplugin/trunk/tracdiscussion/api.py

    r3160 r3517  
    1515from genshi.template import TemplateLoader 
    1616 
    17 from tracdiscussion.notification import * 
     17class IDiscussionFilter(Interface): 
     18    """Extension point interface for components that want to filter discussion 
     19    topics and messages before their addition.""" 
     20 
     21    def filter_topic(req, topic): 
     22        """ Called before new topic creation. May return tuple (False, 
     23        <error_message>) or (True, <topic>) where <error_message> is a message 
     24        that will be displayed when topic creation will be canceled and <topic> 
     25        is modified topic that will be added.""" 
     26 
     27    def filter_message(req, message): 
     28        """ Called before new message creation. May return tuple (False, 
     29        <error_message>) or (True, <message>) where <error_message> is a 
     30        message that will be displayed when message creation will be canceled 
     31        and <message> is modified message that will be added.""" 
     32 
     33 
     34class ITopicChangeListener(Interface): 
     35    """Extension point interface for components that require notification 
     36    when new forum topics are created, modified or deleted.""" 
     37 
     38    def topic_created(topic): 
     39        """Called when a topic is created. Only argument `topic` is 
     40        a dictionary with topic attributes.""" 
     41 
     42    def topic_changed(topic, old_topic): 
     43        """Called when a topic is modified. `old_topic` is a dictionary 
     44        containing the previous values of the topic attributes and `topic` is 
     45        a dictionary with new values that has changed.""" 
     46 
     47    def topic_deleted(topic): 
     48        """Called when a topic is deleted. `topic` argument is a dictionary 
     49        with values of attributes of just deleted topic.""" 
     50 
     51class IMessageChangeListener(Interface): 
     52    """Extension point interface for components that require notification 
     53    when new forum messages are created, modified or deleted.""" 
     54 
     55    def message_created(message): 
     56        """Called when a message is created. Only argument `message` is 
     57        a dictionary with message attributes.""" 
     58 
     59    def message_changed(message, old_message): 
     60        """Called when a message is modified. `old_message` is a dictionary 
     61        containing the previous values of the message attributes and `message` 
     62        is a dictionary with new values that has changed.""" 
     63 
     64    def message_deleted(message): 
     65        """Called when a message is deleted. `message` argument is a dictionary 
     66        with values of attributes of just deleted message.""" 
    1867 
    1968class DiscussionApi(Component): 
    2069 
     70    # Extension points. 
     71    topic_change_listeners = ExtensionPoint(ITopicChangeListener) 
     72    message_change_listeners = ExtensionPoint(IMessageChangeListener) 
     73    discussion_filters = ExtensionPoint(IDiscussionFilter) 
     74 
    2175    # Main request processing function. 
    22  
    2376    def process_discussion(self, context): 
    2477        # Clear data for next request. 
     
    3083 
    3184        # Get request items and modes. 
    32         group, forum, topic, message = self._get_items(context) 
     85        group, forum, topic, message = self._get_context(context) 
    3386        modes = self._get_modes(context, group, forum, topic, message) 
    3487        self.log.debug(modes) 
     
    4598 
    4699        # Perform mode actions. 
    47         self._do_action(context, modes, group, forum, topic, message, 
     100        self._do_actions(context, modes, group, forum, topic, message, 
    48101          is_moderator) 
    49102 
     
    113166        return modes[-1] + '.html', {'discussion' : self.data} 
    114167 
    115     def _get_items(self, context): 
     168    def _get_context(self, context): 
    116169        group, forum, topic, message = None, None, None, None 
    117170 
     
    305358                    return ['forum-list'] 
    306359 
    307     def _do_action(self, context, modes, group, forum, topic, message, 
     360    def _do_actions(self, context, modes, group, forum, topic, message, 
    308361      is_moderator): 
    309362        for mode in modes: 
     
    550603 
    551604                # Get form values. 
    552                 new_subject = context.req.args.get('subject') 
    553                 new_author = context.req.args.get('author') 
    554                 new_body = context.req.args.get('body') 
    555                 new_time = to_timestamp(datetime.now(utc)) 
    556  
    557                 self.log.debug((new_subject, new_body)) 
    558  
    559                 # Add topic. 
    560                 self.add_topic(context, forum['id'], new_subject, new_time, 
    561                   new_author, new_body) 
    562  
    563                 # Get new popic and notify about creation. 
    564                 new_topic = self.get_topic_by_time(context, new_time) 
    565                 to = self.get_topic_to_recipients(context, new_topic['id']) 
    566                 cc = self.get_topic_cc_recipients(context, new_topic['id']) 
    567                 notifier = DiscussionNotifyEmail(self.env) 
    568                 notifier.notify(context, mode, forum, new_topic, None, to, cc) 
     605                topic = {'forum' : forum['id'], 
     606                         'subject' : context.req.args.get('subject'), 
     607                         'author' : context.req.args.get('author'), 
     608                         'body' : context.req.args.get('body'), 
     609                         'time': to_timestamp(datetime.now(utc))} 
     610 
     611                # Add new topic. 
     612                self.add_topic(context, topic) 
     613 
     614                # Get inserted topic with new ID. 
     615                topic = self.get_topic_by_time(context, topic) 
     616 
     617                # Notify change listeners. 
     618                for listener in self.listeners: 
     619                    listener.topic_created(topic) 
    569620 
    570621                # Redirect request to prevent re-submit. 
     
    589640 
    590641                # Get form values. 
    591                 new_subject = context.req.args.get('subject') 
    592                 new_body = context.req.args.get('body') 
    593                 self.log.debug('new_body: ' + new_body) 
     642                old_topic = topic 
     643                topic = {'subject' : context.req.args.get('subject'), 
     644                         'body' : context.req.args.get('body')} 
    594645 
    595646                # Edit topic. 
    596                 topic['subject'] = new_subject 
    597                 topic['body'] = new_body 
    598                 self.edit_topic(context, topic['id'], topic['forum'], 
    599                   topic['subject'], topic['body']) 
     647                self.edit_topic(context, old_topic['id'], topic) 
     648 
     649                # Notify change listeners. 
     650                for listener in self.listeners: 
     651                    listener.topic_changed(topic, old_topic) 
    600652 
    601653                # Redirect request to prevent re-submit. 
     
    761813            self.data['body'] = format_to_html(self.env, context, new_body) 
    762814 
     815        # Get topic messages. 
     816        display = context.req.session.get('message-list-display') 
     817        if display == 'flat-asc': 
     818             messages = self.get_flat_messages(context, topic['id']) 
     819        elif display == 'flat-desc': 
     820             messages = self.get_flat_messages(context, topic['id'], desc = 
     821               True) 
     822        else: 
     823             message = self.get_messages(context, topic['id']) 
     824 
    763825        # Prepare display of messages. 
    764         display = context.req.session.get('message-list-display') 
     826        for message in messages: 
     827            self._format_message(context, visit_time, message) 
    765828        self.data['display'] = display 
    766         if display == 'flat-asc': 
    767             self.data['messages'] = self.get_flat_messages(context, 
    768               topic['id'], visit_time) 
    769         elif display == 'flat-desc': 
    770             self.data['messages'] = self.get_flat_messages(context, 
    771               topic['id'], visit_time, 'ORDER BY time DESC'
    772         else: 
    773             self.data['messages'] = self.get_messages(context, topic['id'], 
    774               visit_time) 
     829        self.data['messages'] = messages 
     830 
     831    def _format_message(self, context, time, message): 
     832        message['author'] = format_to_oneliner(self.env, context, 
     833          message['author']) 
     834        message['body'] = format_to_html(self.env, context, message['body']
     835        message['new'] = int(message['time']) > time 
     836        message['time'] = format_datetime(message['time']) 
     837        return message 
    775838 
    776839    # Get one item functions. 
    777840 
    778     def get_message(self, context, id): 
    779         columns = ('id', 'forum', 'topic', 'replyto', 'time', 'author', 'body') 
    780         sql = "SELECT id, forum, topic, replyto, time, author, body FROM" \ 
    781           " message WHERE id = %s" 
    782         self.env.log.debug(sql % (to_unicode(id),)) 
    783         context.cursor.execute(sql, (to_unicode(id),)) 
     841    def _get_item(self, context, table, columns, where = '', values = ()): 
     842        sql = 'SELECT ' + ', '.join(columns) + ' FROM ' + table + (where 
     843          and (' WHERE ' + where) or '') 
     844        self.log.debug(sql, values) 
     845        context.cursor.execute(sql, values) 
    784846        for row in context.cursor: 
    785847            row = dict(zip(columns, row)) 
     
    787849        return None 
    788850 
     851    def get_message(self, context, id): 
     852        # Get message by ID. 
     853        return self._get_item(context, 'message', ('id', 'forum', 'topic', 
     854          'replyto', 'time', 'author', 'body'), 'id = %s', (id,)) 
     855 
    789856    def get_message_by_time(self, context, time): 
    790         columns = ('id', 'forum', 'topic', 'replyto', 'time', 'author', 'body') 
    791         sql = "SELECT id, forum, topic, replyto, time, author, body FROM" \ 
    792           " message WHERE time = %s" 
    793         self.env.log.debug(sql % (time,)) 
    794         context.cursor.execute(sql, (time,)) 
     857        # Get message by time of creation. 
     858        return self._get_item(context, 'message', ('id', 'forum', 'topic', 
     859          'replyto', 'time', 'author', 'body'), 'time = %s', (time,)) 
     860 
     861    def get_topic(self, context, id): 
     862        # Get topic by ID. 
     863        return self._get_item(context, 'topic', ('id', 'forum', 'subject', 
     864          'time', 'author', 'body'), 'id = %s', (id,)) 
     865 
     866    def get_topic_by_time(self, context, time): 
     867        # Get topic by time of creation. 
     868        return self._get_item(context, 'topic', ('id', 'forum', 'subject', 
     869          'time', 'author', 'body'), 'time = %s', (time,)) 
     870 
     871    def get_topic_by_subject(self, context, subject): 
     872        # Get topic by subject. 
     873        return self._get_item(context, 'topic', ('id', 'forum', 'subject', 
     874          'time', 'author', 'body'), 'subject = %s', (subject,)) 
     875 
     876    def get_forum(self, context, id): 
     877        # Get forum by ID. 
     878        forum = self._get_item(context, 'forum', ('id', 'group', 'name', 
     879          'subject', 'time', 'moderators', 'description'), 'id = %s', (id,)) 
     880 
     881        # Fix list of moderators. 
     882        if forum: 
     883           forum['moderators'] = forum['moderators'].split(' ') 
     884 
     885        return forum 
     886 
     887    def get_group(self, context, id): 
     888        # Get forum group or none group. 
     889        return self.get_item(context, 'group', ('id', 'name', 'description'), 
     890          'id = %s', (id,)) or {'id' : 0, 'name': 'None', 'description': 
     891          'No Group'} 
     892 
     893    # Get list functions. 
     894 
     895    def _get_items(self, context, table, columns, where = '', values = (), 
     896      order_by = '', desc = False): 
     897        sql = 'SELECT ' + ', '.join(columns) + ' FROM ' + table + (where 
     898          and (' WHERE ' + where) or '') + (order_by and (' ORDER BY ' + 
     899          order_by + (' ASC', ' DESC')[bool(desc)]) or '') 
     900        self.log.debug(sql % values) 
     901        context.cursor.execute(sql, values) 
     902        items = [] 
    795903        for row in context.cursor: 
    796904            row = dict(zip(columns, row)) 
    797             return row 
    798         return None 
    799  
    800     def get_topic(self, context, id): 
    801         columns = ('id', 'forum', 'subject', 'time', 'author', 'body') 
    802         sql = "SELECT id, forum, subject, time, author, body FROM topic WHERE" \ 
    803           " id = %s" 
    804         self.env.log.debug(sql % (to_unicode(id),)) 
    805         context.cursor.execute(sql, (to_unicode(id),)) 
    806         for row in context.cursor: 
    807             row = dict(zip(columns, row)) 
    808             return row 
    809         return None 
    810  
    811     def get_topic_by_time(self, context, time): 
    812         columns = ('id', 'forum', 'subject', 'time', 'author', 'body') 
    813         sql = "SELECT id, forum, subject, time, author, body FROM topic WHERE" \ 
    814           " time = %s" 
    815         self.env.log.debug(sql % (time,)) 
    816         context.cursor.execute(sql, (time,)) 
    817         for row in context.cursor: 
    818             row = dict(zip(columns, row)) 
    819             return row 
    820         return None 
    821  
    822     def get_topic_by_subject(self, context, subject): 
    823         columns = ('id', 'forum', 'subject', 'time', 'author', 'body') 
    824         sql = "SELECT id, forum, subject, time, author, body FROM topic WHERE" \ 
    825           " subject = %s" 
    826         self.env.log.debug(sql % (subject,)) 
    827         context.cursor.execute(sql, (subject,)) 
    828         for row in context.cursor: 
    829             row = dict(zip(columns, row)) 
    830             return row 
    831         return None 
    832  
    833     def get_topic_to_recipients(self, context, id): 
    834         sql = "SELECT t.author FROM topic t WHERE t.id = %s UNION SELECT" \ 
    835           " m.author FROM message m WHERE m.topic = %s" 
    836         self.env.log.debug(sql % (to_unicode(id), to_unicode(id))) 
    837         context.cursor.execute(sql, (to_unicode(id), to_unicode(id))) 
    838         to_recipients = [] 
    839         for row in context.cursor: 
    840             to_recipients.append(row[0]) 
    841         return to_recipients 
    842  
    843     def get_topic_cc_recipients(self, context, id): 
    844         return [] 
    845  
    846     def get_forum(self, context, id): 
    847         columns = ('id', 'group', 'name', 'subject', 'time', 'moderators', 
    848           'description') 
    849         sql = "SELECT id, forum_group, name, subject, time, moderators," \ 
    850            " description FROM forum WHERE id = %s" 
    851         self.env.log.debug(sql % (to_unicode(id),)) 
    852         context.cursor.execute(sql, (to_unicode(id),)) 
    853         for row in context.cursor: 
    854             row = dict(zip(columns, row)) 
    855             row['moderators'] = row['moderators'].split(' ') 
    856             return row 
    857         return None 
    858  
    859     def get_group(self, context, id): 
    860         columns = ('id', 'name', 'description') 
    861         sql = "SELECT id, name, description FROM forum_group WHERE id = %s" 
    862         self.env.log.debug(sql % (to_unicode(id),)) 
    863         context.cursor.execute(sql, (to_unicode(id),)) 
    864         for row in context.cursor: 
    865             row = dict(zip(columns, row)) 
    866             return row 
    867         return {'id' : 0, 'name': 'None', 'description': 'No Group'} 
    868  
    869     # Get list functions. 
     905            items.append(row) 
     906        return items 
    870907 
    871908    def get_groups(self, context, order_by = 'id', desc = False): 
     
    10331070        for row in context.cursor: 
    10341071            row = dict(zip(columns, row)) 
    1035             row['author'] = format_to_oneliner(self.env, context, row['author']) 
    1036             row['body'] = format_to_html(self.env, context, row['body']) 
    1037             if int(row['time']) > time: 
    1038                 row['new'] = True 
    1039             row['time'] = format_datetime(row['time']) 
    10401072            messagemap[row['id']] = row 
    10411073 
     
    10541086        return messages; 
    10551087 
    1056     def get_flat_messages(self, context, topic_id, time, order_by = 
    1057       'ORDER BY time ASC'): 
    1058         columns = ('id', 'replyto', 'time', 'author', 'body') 
    1059         sql = "SELECT m.id, m.replyto, m.time, m.author, m.body FROM message m" \ 
    1060           " WHERE m.topic = %s " + order_by 
    1061         self.env.log.debug(sql % (to_unicode(topic_id),)) 
    1062         context.cursor.execute(sql, (to_unicode(topic_id),)) 
    1063         messages = [] 
    1064         for row in context.cursor: 
    1065             row = dict(zip(columns, row)) 
    1066             row['author'] = format_to_oneliner(self.env, context, row['author']) 
    1067             row['body'] = format_to_html(self.env, context, row['body']) 
    1068             if int(row['time']) > time: 
    1069                 row['new'] = True 
    1070             row['time'] = format_datetime(row['time']) 
    1071             messages.append(row) 
    1072         return messages 
     1088    def get_flat_messages(self, context, id, order_by = 'time', desc = False): 
     1089        # Return messages of specified topic. 
     1090        return self._get_items(context, 'message', ('id', 'replyto', 'time', 
     1091          'author', 'body'), 'topic = %s', (id,), order_by, desc) 
     1092 
     1093    def get_replies(self, context, id, order_by = 'time', desc = False): 
     1094        # Return replies of specified message. 
     1095        return self._get_items(context, 'message', ('id', 'replyto', 'time', 
     1096          'author', 'body'), where = 'replyto = %s', values = (id,), order_by 
     1097          = order_by, desc = desc) 
    10731098 
    10741099    def get_users(self, context): 
     1100        # Return users that Trac knows. 
    10751101        users = [] 
    10761102        for user in self.env.get_known_users(): 
     
    10801106    # Add items functions. 
    10811107 
    1082     def add_group(self, context, name, description): 
    1083         sql = "INSERT INTO forum_group (name, description) VALUES (%s, %s)" 
    1084         self.env.log.debug(sql % (name, description)) 
    1085         context.cursor.execute(sql, (name, description)) 
    1086  
    1087     def add_forum(self, context, name, author, subject, description, moderators, 
    1088       group): 
    1089         moderators = ' '.join(moderators) 
    1090         sql = "INSERT INTO forum (name, author, time, moderators, subject," \ 
    1091           " description, forum_group) VALUES (%s, %s, %s, %s, %s, %s, %s)" 
    1092         self.env.log.debug(sql % (name, author, to_timestamp(datetime.now(utc)), 
    1093           moderators, subject, description, group)) 
    1094         context.cursor.execute(sql, (name, author, to_timestamp(datetime.now(utc)), 
    1095           moderators, subject, description, group)) 
    1096  
    1097     def add_topic(self, context, forum, subject, time, author, body): 
    1098         sql = "INSERT INTO topic (forum, subject, time, author, body) VALUES" \ 
    1099           " (%s, %s, %s, %s, %s)" 
    1100         self.env.log.debug(sql % (forum, subject, time, author, body)) 
    1101         context.cursor.execute(sql, (forum, subject, time, author, body)) 
    1102  
    1103     def add_message(self, context, forum, topic, replyto, time, author, body): 
    1104         sql = "INSERT INTO message (forum, topic, replyto, time, author," \ 
    1105           " body) VALUES (%s, %s, %s, %s, %s, %s)" 
    1106         self.env.log.debug(sql % (forum, topic, replyto, time, author, body)) 
    1107         context.cursor.execute(sql, (forum, topic, replyto, time, author, body)) 
     1108    def _add_item(self, context, table, item): 
     1109        fields = item.keys() 
     1110        values = item.values() 
     1111        sql = "INSERT INTO %s (" % (table,) + ", ".join(fields) + ") VALUES (" \ 
     1112          + ", ".join(["%s" for I in xrange(len(fields))]) + ")" 
     1113        self.log.debug(sql % tuple(values)) 
     1114        context.cursor.execute(sql, tuple(values)) 
     1115 
     1116    def add_group(self, context, group): 
     1117        self._add_item(context, 'group', group) 
     1118  
     1119    def add_forum(self, context, forum): 
     1120        forum['moderators'] = ' '.join(forum['moderators']) 
     1121        self._add_item(context, 'forum', forum) 
     1122 
     1123    def add_topic(self, context, topic): 
     1124        self._add_item(context, 'topic', topic) 
     1125 
     1126    def add_message(self, context, message): 
     1127        self._add_item(context, 'message', message) 
    11081128 
    11091129    # Delete items functions. 
    11101130 
    1111     def delete_group(self, context, group): 
    1112         sql = "DELETE FROM forum_group WHERE id = %s" 
    1113         self.env.log.debug(sql % (to_unicode(group),)) 
    1114         context.cursor.execute(sql, (to_unicode(group),)) 
    1115         sql = "UPDATE forum SET forum_group = 0 WHERE forum_group = %s" 
    1116         self.env.log.debug(sql % (to_unicode(group),)) 
    1117         context.cursor.execute(sql, (to_unicode(group),)) 
    1118  
    1119     def delete_forum(self, context, forum): 
    1120         sql = "DELETE FROM message WHERE forum = %s" 
    1121         self.env.log.debug(sql % (to_unicode(forum),)) 
    1122         context.cursor.execute(sql, (to_unicode(forum),)) 
    1123         sql = "DELETE FROM topic WHERE forum = %s" 
    1124         self.env.log.debug(sql % (to_unicode(forum),)) 
    1125         context.cursor.execute(sql, (to_unicode(forum),)) 
    1126         sql = "DELETE FROM forum WHERE id = %s" 
    1127         self.env.log.debug(sql % (to_unicode(forum),)) 
    1128         context.cursor.execute(sql, (to_unicode(forum),)) 
    1129  
    1130     def delete_topic(self, context, topic): 
    1131         sql = "DELETE FROM message WHERE topic = %s" 
    1132         self.env.log.debug(sql % (to_unicode(topic),)) 
    1133         context.cursor.execute(sql, (to_unicode(topic),)) 
    1134         sql = "DELETE FROM topic WHERE id = %s" 
    1135         self.env.log.debug(sql % (to_unicode(topic),)) 
    1136         context.cursor.execute(sql, (to_unicode(topic),)) 
    1137  
    1138     def delete_message(self, context, message): 
    1139         # Get message replies. 
    1140         sql = "SELECT m.id FROM message m WHERE m.replyto = %s" 
    1141         self.env.log.debug(sql % (to_unicode(message),)) 
    1142         context.cursor.execute(sql, (to_unicode(message),)) 
    1143         replies = [] 
    1144  
    1145         # Get all replies first. 
    1146         for row in context.cursor: 
    1147             replies.append(row[0]) 
    1148  
    1149         # Delete all replies. 
    1150         for reply in replies: 
    1151             self.delete_message(context, reply) 
     1131    def _delete_item(self, context, table, where = '', values = ()): 
     1132        sql = 'DELETE FROM ' + table + (where and (' WHERE ' + where) or '') 
     1133        self.env.log.debug(sql % values) 
     1134        context.cursor.execute(sql, values) 
     1135 
     1136    def delete_group(self, context, id): 
     1137        # Delete group. 
     1138        self._delete_item(context, 'forum_group', 'id = %s', (id,)) 
     1139 
     1140        # Assing forums of this group to none group. 
     1141        self._set_item(context, 'forum', 'forum_group', '0', 'forum_group = %s', 
     1142          (id,)) 
     1143 
     1144    def delete_forum(self, context, id): 
     1145        # Delete all messages of this forum. 
     1146        self._delete_item(context, 'message', 'forum = %s', (id,)) 
     1147 
     1148        # Delete all topics of this forum. 
     1149        self._delete_item(context, 'topic', 'forum = %s', (id,)) 
     1150 
     1151        # Finally delete forum. 
     1152        self._delete_item(context, 'forum', 'id = %s', (id,)) 
     1153 
     1154    def delete_topic(self, context, id): 
     1155        # Delete all messages of this topic. 
     1156        self._delete_item(context, 'message', 'topic = %s', (id,)) 
     1157 
     1158        # Delete topic itself. 
     1159        self._delete_item(context, 'topic', 'id = %s', (id,)) 
     1160 
     1161    def delete_message(self, context, id): 
     1162        # Delete all replies of this message. 
     1163        for reply in self.get_replies(context, id): 
     1164            self.delete_message(context, reply['id']) 
    11521165 
    11531166        # Delete message itself. 
    1154         sql = "DELETE FROM message WHERE id = %s" 
    1155         self.env.log.debug(sql % (to_unicode(message),)) 
    1156         context.cursor.execute(sql, (to_unicode(message),)) 
     1167        self._delete_item(context, 'message', 'id = %s', (id,)) 
    11571168 
    11581169    # Set item functions. 
    11591170 
    1160     def set_group(self, context, forum, group): 
    1161         if not group: 
    1162             group = '0' 
    1163         sql = "UPDATE forum SET forum_group = %s WHERE id = %s" 
    1164         self.env.log.debug(sql % (group, forum)) 
    1165         context.cursor.execute(sql, (group, forum)) 
    1166  
    1167     def set_forum(self, context, topic, forum): 
    1168         sql = "UPDATE topic SET forum = %s WHERE id = %s" 
    1169         self.env.log.debug(sql % (forum, topic)) 
    1170         context.cursor.execute(sql, (forum, topic)) 
    1171         sql = "UPDATE message SET forum = %s WHERE topic = %s" 
    1172         self.env.log.debug(sql % (forum, topic)) 
    1173         context.cursor.execute(sql, (forum, topic)) 
     1171    def _set_item(self, context, table, field, value, where = '', values = ()): 
     1172        sql = 'UPDATE ' + table + ' SET ' + field + ' = "' + to_unicode(value) \ 
     1173          + '"' + (where and (' WHERE ' + where) or '') 
     1174        self.env.log.debug(sql % values) 
     1175        context.cursor.execute(sql, values) 
     1176 
     1177    def set_group(self, context, forum_id, group_id): 
     1178        # Change group of specified forum. 
     1179        self._set_item(context, 'forum', 'forum_group', group_id or '0', 
     1180          'id = %s', (forum_id,)) 
     1181 
     1182    def set_forum(self, context, topic_id, forum_id): 
     1183        # Change forum of all topics and messages. 
     1184        self._set_item(context, 'topic', 'forum', forum_id, 'id = %s', 
     1185          (topic_id,)) 
     1186        self._set_item(context, 'message', 'forum', forum_id, 'topic = %s', 
     1187          (topic_id,)) 
    11741188 
    11751189    # Edit functions. 
    11761190 
    1177     def edit_group(self, context, group, name, description): 
    1178         sql = "UPDATE forum_group SET name = %s, description = %s WHERE id = %s" 
    1179         self.env.log.debug(sql % (name, description, group)) 
    1180         context.cursor.execute(sql, (name, description, group)) 
    1181  
    1182     def edit_forum(self, context, forum, name, subject, description, moderators, 
    1183       group): 
    1184         moderators = ' '.join(moderators) 
    1185         if not group: 
    1186             group = '0' 
    1187         sql = "UPDATE forum SET name = %s, subject = %s, description = %s," \ 
    1188           " moderators = %s, forum_group = %s WHERE id = %s" 
    1189         self.env.log.debug(sql % (name, subject, description, moderators, 
    1190           group, forum)) 
    1191         context.cursor.execute(sql, (name, subject, description, moderators, 
    1192           group, forum)) 
    1193  
    1194     def edit_topic(self, context, topic, forum, subject, body): 
    1195         sql = "UPDATE topic SET forum = %s, subject = %s, body = %s WHERE id" \ 
    1196           " = %s" 
    1197         self.env.log.debug(sql % (forum, subject, body, topic)) 
    1198         context.cursor.execute(sql, (forum, subject, body, topic)) 
    1199  
    1200     def edit_message(self, context, message, forum, topic, replyto, body): 
    1201         sql = "UPDATE message SET forum = %s, topic = %s, replyto = %s, body" \ 
    1202           " = %s WHERE id = %s" 
    1203         self.env.log.debug(sql % (forum, topic, replyto, body, message)) 
    1204         context.cursor.execute(sql, (forum, topic, replyto, body, message)) 
     1191    def _edit_item(self, context, table, id, item): 
     1192        fields = item.keys() 
     1193        values = item.values() 
     1194        sql = "UPDATE %s SET " % (table,) + ", ".join([("%s = %%s" % (field)) 
     1195          for field in fields]) + " WHERE id = %s" 
     1196        self.log.debug(sql % tuple(values + [id])) 
     1197        context.cursor.execute(sql, tuple(values + [id])) 
     1198 
     1199    def edit_group(self, context, id, group): 
     1200        # Edit froum group. 
     1201        self._edit_item(context, 'forum_group', id, group) 
     1202 
     1203    def edit_forum(self, context, id, forum): 
     1204        # Fix forum fields. 
     1205        forum['moderators'] = ' '.join(forum['moderators']) 
     1206        forum['group'] = forum['group'] or '0' 
     1207 
     1208        # Edit forum. 
     1209        self._edit_item(context, 'forum', id, forum) 
     1210 
     1211    def edit_topic(self, context, id, topic): 
     1212        # Edit topic. 
     1213        self._edit_item(context, 'topic', id, topic) 
     1214 
     1215    def edit_message(self, context, id, message): 
     1216        # Edit message, 
     1217        self._edit_item(context, 'message', id, message) 
  • discussionplugin/trunk/tracdiscussion/timeline.py

    r3160 r3517  
    5757            # Get message events 
    5858            for message in self._get_changed_messages(context, start, stop): 
    59                 title = 'New repy on %s created' % (message['forum_name']) 
     59                title = 'New reply on %s created' % (message['forum_name']) 
    6060                description = message['topic_subject'] 
    6161                href = context.req.href.discussion(message['forum'], 
  • discussionplugin/trunk/tracdiscussion/wiki.py

    r2837 r3517  
    114114                row = dict(zip(columns, row)) 
    115115                return html.a(label, href = formatter.href.discussion(id), 
    116                   title = row['subject']
     116                  title = row['subject'].replace('"', '')
    117117            return html.a(label, href = '%s/%s' % (formatter.href.discussion(), 
    118118              id), title = label, class_ = 'missing') 
     
    127127                return html.a(label, href = '%s#-1' % \ 
    128128                  (formatter.href.discussion(row['forum'], id),), title = 
    129                   '%s: %s' % (row['forum_subject'], row['subject'])) 
     129                  ('%s: %s' % (row['forum_subject'], row['subject'])) 
     130                  .replace('"', '')) 
    130131            return html.a(label, href = '%s/%s' % (formatter.href.discussion(), 
    131               id), title = label, class_ = 'missing') 
     132              id), title = label.replace('"', ''), class_ = 'missing') 
    132133        elif ns == 'message': 
    133134            columns = ('forum', 'topic', 'forum_subject', 'subject') 
     
    142143                return html.a(label, href = '%s#%s' % \ 
    143144                  (formatter.href.discussion(row['forum'], row['topic'], id), 
    144                   id), title = '%s: %s' % (row['forum_subject'], 
    145                   row['subject'])) 
     145                  id), title = ('%s: %s' % (row['forum_subject'], 
     146                  row['subject'])).replace('"', '')) 
    146147            return html.a(label, href = '%s/%s' % (formatter.href.discussion(), 
    147               id), title = label, class_ = 'missing') 
     148              id), title = label.replace('"', ''), class_ = 'missing') 
    148149        else: 
    149150            return html.a(label, href = '%s/%s' % (formatter.href.discussion(), 
    150               id), title = label, class_ = 'missing') 
     151              id), title = label.replace('"', ''), class_ = 'missing')