# HG changeset patch # User Paul Boddie # Date 1383486211 -3600 # Node ID b84e6a7a44b2ef8870adee452361afb8a5d6ee68 Started a separate project from ConfluenceConverter for subpage comments. diff -r 000000000000 -r b84e6a7a44b2 actions/PostComment.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/actions/PostComment.py Sun Nov 03 14:43:31 2013 +0100 @@ -0,0 +1,128 @@ +# -*- coding: iso-8859-1 -*- +""" + MoinMoin - PostComment action + + @copyright: 2013 by Paul Boddie + @license: GNU GPL (v2 or later), see COPYING.txt for details. +""" + +from MoinMoin.action import ActionBase +from MoinMoin.PageEditor import PageEditor +from MoinMoin.security import Permissions +from MoinMoin.wikiutil import escape +from MoinSupport import getPagesForSearch, getPagesFromResults, ActionSupport + +Dependencies = ['pages'] + +class SpecialPermissions(Permissions): + + "Permit saving of ACL-enabled comment pages." + + def __init__(self, user, pagename): + Permissions.__init__(self, user) + self.pagename = pagename + + def admin(self, pagename): + return pagename == self.pagename + +class PostComment(ActionBase, ActionSupport): + + "Post a comment to the wiki." + + def get_form_html(self, buttons_html): + + "Return the action's form incorporating the 'buttons_html'." + + _ = self._ + request = self.request + form = self.get_form() + + comment = form.get("comment", [""])[0] + + d = { + "comment_label" : escape(comment and _("Please review your comment.") or _("Write a comment in the box.")), + "comment_default" : escape(comment), + "buttons_html" : buttons_html, + } + + return u"""\ +

%(comment_label)s

+ +

%(buttons_html)s

+""" % d + + def do_action(self): + + "Attempt to post a comment." + + _ = self._ + request = self.request + form = self.get_form() + + comment = form.get("comment", [""])[0] + + if not comment.strip(): + return 0, _("A comment should have some content.") + + if not request.user.valid or not request.user.may.write(self.pagename): + return 0, _("You are not allowed to comment on this page.") + + # Determine the last comment. + + comments = get_comment_numbers(self.pagename, request) + last_comment_pagename = comments and comments[-1] or -1 + + # Write the new page. + + comment_pagename = "%s/%04d" % (self.pagename, last_comment_pagename + 1) + new_page = PageEditor(request, comment_pagename) + username = request.user.name + + try: + # To add a page with an ACL, a special policy is required. + + may = request.user.may + request.user.may = SpecialPermissions(request.user, comment_pagename) + + # Save the page, labelling it with the actual username. + + try: + new_page.saveText(comment_template % (username, username, comment), 0) + + # Restore the superusers. + + finally: + request.user.may = may + + return 1, _("Comment added.") + except new_page.SaveError, exc: + return 0, unicode(exc) + +comment_template = """\ +#acl %s:read,write,delete,revert All:read +#pragma comment-owner %s +%s""" + +def get_comment_numbers(pagename, request): + + """ + Return a list of comment numbers associated with the given 'pagename', using + the 'request' provided. + """ + + pagenames = [] + + for page in getPagesForSearch("title:regex:^%s/" % pagename, request): + basename, number = page.page_name.rsplit("/", 1) + if basename == pagename and number.isdigit(): + pagenames.append(int(number)) + + pagenames.sort() + return pagenames + +# Action invocation function. + +def execute(pagename, request): + PostComment(pagename, request).render() + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 000000000000 -r b84e6a7a44b2 macros/IncludeComments.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/macros/IncludeComments.py Sun Nov 03 14:43:31 2013 +0100 @@ -0,0 +1,157 @@ +# -*- coding: iso-8859-1 -*- +""" + MoinMoin - IncludeComments Macro + + @copyright: 2013 by Paul Boddie + @license: GNU GPL (v2 or later), see COPYING.txt for details. + + Code from the Include macro: + + @copyright: 2000-2004 Juergen Hermann , + 2000-2001 Richard Jones + @license: GNU GPL (v2 or later), see COPYING.txt for details. +""" + +from MoinMoin.Page import Page +from MoinMoin.macro import Include +from MoinMoin.user import User +from MoinMoin.wikiutil import escape +import re +import codecs + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + +Dependencies = ['pages'] + +# Macro functions. + +def execute(macro, text): + request = macro.request + fmt = request.formatter + page = request.page + pagename = page.page_name + _ = request.getText + + output = [] + append = output.append + + # Add a heading. + + append(fmt.heading(on=1, depth=1)) + append(fmt.text(_("Comments"))) + append(fmt.heading(on=0, depth=1)) + + # Provide a form for adding new comments. + + if request.user.valid and request.user.may.write(pagename): + + d = { + "show_form" : escape(_("Add a comment to this page.")), + "comment_label" : escape(_("Write a comment in the box.")), + "comment_default" : "", + "submit" : escape(_("Submit this comment")), + } + + append("""\ +
+%(show_form)s +
+

%(comment_label)s

+ +

+
+
+""" % d) + + # NOTE: Much of the code below originates from the Include macro, but it + # NOTE: excludes various options of that macro and adds comment-related + # NOTE: output. + + # Add included comments. + + filterfn = re.compile(ur"^%s/" % re.escape(pagename), re.U).match + pages = request.rootpage.getPageList(filter=filterfn) + pages.sort() + + ownerfn = re.compile("^#pragma comment-owner (.*?)$", re.MULTILINE | re.UNICODE).search + + # Track included pages. + + if not hasattr(page, '_macroInclude_pagelist'): + page._macroInclude_pagelist = {} + + # Visit each comment page. + + for inc_name in pages: + + # Skip unreadable or already included pages. + + if not request.user.may.read(inc_name): + continue + if inc_name in page._macroInclude_pagelist: + continue + + # Obtain a separate formatter for the included page. + + inc_fmt = macro.formatter.__class__(request, is_included=True) + inc_fmt._base_depth = macro.formatter._base_depth + + # Obtain the included page. + + inc_page = Page(request, inc_name, formatter=inc_fmt) + if not inc_page.exists(): + continue + inc_page._macroInclude_pagelist = page._macroInclude_pagelist + + if not hasattr(request, "_Include_backto"): + request._Include_backto = pagename + + # Output a container for the included page. + + append(fmt.div(1, id=inc_name, css_class="included-comment")) + + # Add a label indicating a comment. + + match = ownerfn(inc_page.get_raw_body()) + if match: + user = User(request, auth_username=match.group(1)) + if user.exists(): + append(fmt.div(1, css_class="included-comment-owner")) + append(fmt.text(user.aliasname or user.name)) + append(fmt.div(0)) + + # Set or increment include marker. + + page._macroInclude_pagelist[inc_name] = \ + page._macroInclude_pagelist.get(inc_name, 0) + 1 + + # Output the included page. + + strfile = codecs.getwriter("utf-8")(StringIO()) + request.redirect(strfile) + try: + inc_page.send_page(content_only=True, + omit_footnotes=True, + count_hit=False) + append(unicode(strfile.getvalue(), "utf-8")) + finally: + request.redirect() + + # Decrement or remove include marker. + + if page._macroInclude_pagelist[inc_name] > 1: + page._macroInclude_pagelist[inc_name] = \ + page._macroInclude_pagelist[inc_name] - 1 + else: + del page._macroInclude_pagelist[inc_name] + + # Close the container for the included page. + + append(fmt.div(0)) + + return u"".join(output) + +# vim: tabstop=4 expandtab shiftwidth=4