| 1 |
# -*- coding: utf8 -*- |
|---|
| 2 |
|
|---|
| 3 |
from tracdiscussion.api import * |
|---|
| 4 |
from tracdiscussion.core import * |
|---|
| 5 |
from trac.core import * |
|---|
| 6 |
from trac.wiki import IWikiSyntaxProvider, IWikiMacroProvider |
|---|
| 7 |
from trac.web.main import IRequestHandler, IRequestFilter |
|---|
| 8 |
from trac.web.chrome import add_stylesheet |
|---|
| 9 |
from trac.util import format_datetime |
|---|
| 10 |
from trac.util.html import html |
|---|
| 11 |
from trac.util.text import to_unicode |
|---|
| 12 |
import time, re |
|---|
| 13 |
|
|---|
| 14 |
view_topic_doc = """Displays content of discussion topic. If no argument passed |
|---|
| 15 |
tries to find topic with same name as name of current wiki page. If topic name |
|---|
| 16 |
passed displays that topic. """ |
|---|
| 17 |
|
|---|
| 18 |
class DiscussionWiki(Component): |
|---|
| 19 |
""" |
|---|
| 20 |
The wiki module implements macros for forums, topics and messages |
|---|
| 21 |
referencing. |
|---|
| 22 |
""" |
|---|
| 23 |
implements(IWikiSyntaxProvider, IWikiMacroProvider, IRequestFilter) |
|---|
| 24 |
|
|---|
| 25 |
# IWikiSyntaxProvider methods |
|---|
| 26 |
|
|---|
| 27 |
def get_link_resolvers(self): |
|---|
| 28 |
yield ('forum', self._discussion_link) |
|---|
| 29 |
yield ('topic', self._discussion_link) |
|---|
| 30 |
yield ('message', self._discussion_link) |
|---|
| 31 |
|
|---|
| 32 |
def get_wiki_syntax(self): |
|---|
| 33 |
return [] |
|---|
| 34 |
|
|---|
| 35 |
# IWikiMacroProvider methods |
|---|
| 36 |
|
|---|
| 37 |
def get_macros(self): |
|---|
| 38 |
yield 'ViewTopic' |
|---|
| 39 |
|
|---|
| 40 |
def get_macro_description(self, name): |
|---|
| 41 |
if name == 'VisitCounter': |
|---|
| 42 |
return view_topic_doc |
|---|
| 43 |
else: |
|---|
| 44 |
return "" |
|---|
| 45 |
|
|---|
| 46 |
def render_macro(self, req, name, content): |
|---|
| 47 |
if name == 'ViewTopic': |
|---|
| 48 |
self.log.debug("Rendering ViewTopic macro...") |
|---|
| 49 |
|
|---|
| 50 |
# Determine topic subject |
|---|
| 51 |
if content: |
|---|
| 52 |
subject = content |
|---|
| 53 |
else: |
|---|
| 54 |
subject = req.path_info[6:] or 'WikiStart' |
|---|
| 55 |
|
|---|
| 56 |
# Get database access. |
|---|
| 57 |
db = self.env.get_db_cnx() |
|---|
| 58 |
cursor = db.cursor() |
|---|
| 59 |
|
|---|
| 60 |
# Get topic by subject |
|---|
| 61 |
api = self.env[DiscussionApi] |
|---|
| 62 |
topic = api.get_topic_by_subject(cursor, subject) |
|---|
| 63 |
self.log.debug('subject: %s' % (subject,)) |
|---|
| 64 |
self.log.debug('topic: %s' % (topic,)) |
|---|
| 65 |
|
|---|
| 66 |
# Return macro content |
|---|
| 67 |
req.args['component'] = 'wiki' |
|---|
| 68 |
if topic: |
|---|
| 69 |
req.args['forum'] = topic['forum'] |
|---|
| 70 |
req.args['topic'] = topic['id'] |
|---|
| 71 |
return to_unicode(req.hdf.render(api.render_discussion(req)[0])) |
|---|
| 72 |
else: |
|---|
| 73 |
raise TracError('Not implemented macro %s' % (name)) |
|---|
| 74 |
|
|---|
| 75 |
# IRequestFilter methods |
|---|
| 76 |
def pre_process_request(self, req, handler): |
|---|
| 77 |
# Change method from POST to GET. |
|---|
| 78 |
match = re.match(r'^/wiki(?:/(.*))?', req.path_info) |
|---|
| 79 |
action = req.args.get('discussion_action') |
|---|
| 80 |
if match and action and req.method == 'POST': |
|---|
| 81 |
req.environ['REQUEST_METHOD'] = 'GET' |
|---|
| 82 |
|
|---|
| 83 |
# Continue processing request. |
|---|
| 84 |
return handler |
|---|
| 85 |
|
|---|
| 86 |
def post_process_request(self, req, template, content_type): |
|---|
| 87 |
return (template, content_type) |
|---|
| 88 |
|
|---|
| 89 |
# Core code methods |
|---|
| 90 |
def _discussion_link(self, formatter, ns, params, label): |
|---|
| 91 |
id = params |
|---|
| 92 |
|
|---|
| 93 |
# Get database access. |
|---|
| 94 |
db = self.env.get_db_cnx() |
|---|
| 95 |
cursor = db.cursor() |
|---|
| 96 |
|
|---|
| 97 |
if ns == 'forum': |
|---|
| 98 |
columns = ('subject',) |
|---|
| 99 |
sql = "SELECT f.subject FROM forum f WHERE f.id = %s" |
|---|
| 100 |
self.log.debug(sql % (id,)) |
|---|
| 101 |
cursor.execute(sql, (id,)) |
|---|
| 102 |
for row in cursor: |
|---|
| 103 |
row = dict(zip(columns, row)) |
|---|
| 104 |
return html.a(label, href = formatter.href.discussion(id), |
|---|
| 105 |
title = row['subject'].replace('"', '')) |
|---|
| 106 |
return html.a(label, href = '%s/%s' % (formatter.href.discussion(), |
|---|
| 107 |
id), title = label.replace('"', ''), class_ = 'missing') |
|---|
| 108 |
elif ns == 'topic': |
|---|
| 109 |
columns = ('forum', 'forum_subject', 'subject') |
|---|
| 110 |
sql = "SELECT t.forum, f.subject, t.subject FROM topic t LEFT" \ |
|---|
| 111 |
" JOIN forum f ON t.forum = f.id WHERE t.id = %s" |
|---|
| 112 |
self.log.debug(sql % (id,)) |
|---|
| 113 |
cursor.execute(sql, (id,)) |
|---|
| 114 |
for row in cursor: |
|---|
| 115 |
row = dict(zip(columns, row)) |
|---|
| 116 |
return html.a(label, href = '%s#-1' % \ |
|---|
| 117 |
(formatter.href.discussion(row['forum'], id),), title = |
|---|
| 118 |
('%s: %s' % (row['forum_subject'], row['subject'])) |
|---|
| 119 |
.replace('"', '')) |
|---|
| 120 |
return html.a(label, href = '%s/%s' % (formatter.href.discussion(), |
|---|
| 121 |
id), title = label.replace('"', ''), class_ = 'missing') |
|---|
| 122 |
elif ns == 'message': |
|---|
| 123 |
columns = ('forum', 'topic', 'forum_subject', 'subject') |
|---|
| 124 |
sql = "SELECT m.forum, m.topic, f.subject, t.subject FROM" \ |
|---|
| 125 |
" message m, (SELECT subject, id FROM forum) f," \ |
|---|
| 126 |
" (SELECT subject, id FROM topic) t WHERE" \ |
|---|
| 127 |
" m.forum = f.id AND m.topic = t.id AND m.id = %s" |
|---|
| 128 |
self.log.debug(sql % (id,)) |
|---|
| 129 |
cursor.execute(sql, (id,)) |
|---|
| 130 |
for row in cursor: |
|---|
| 131 |
row = dict(zip(columns, row)) |
|---|
| 132 |
return html.a(label, href = '%s#%s' % \ |
|---|
| 133 |
(formatter.href.discussion(row['forum'], row['topic'], id), |
|---|
| 134 |
id), title = ('%s: %s' % (row['forum_subject'], |
|---|
| 135 |
row['subject'])).replace('"', '')) |
|---|
| 136 |
return html.a(label, href = '%s/%s' % (formatter.href.discussion(), |
|---|
| 137 |
id), title = label.replace('"', ''), class_ = 'missing') |
|---|
| 138 |
else: |
|---|
| 139 |
return html.a(label, href = '%s/%s' % (formatter.href.discussion(), |
|---|
| 140 |
id), title = label.replace('"', ''), class_ = 'missing') |
|---|