# HG changeset patch # User Paul Boddie # Date 1383435949 -3600 # Node ID 6ad31856efbffe184b2dfd2e1c0d0b5e30c9656d # Parent 7107bc9e783159485b4a5582c16a2bc6b456c219 Improved the comment inclusion to show comment authors, and the comment posting (and wiki conversion) to set ACLs and authorship/ownership details in comments. diff -r 7107bc9e7831 -r 6ad31856efbf actions/PostComment.py --- a/actions/PostComment.py Sat Nov 02 20:08:45 2013 +0100 +++ b/actions/PostComment.py Sun Nov 03 00:45:49 2013 +0100 @@ -8,11 +8,23 @@ 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." @@ -62,14 +74,35 @@ # Write the new page. - new_page = PageEditor(request, "%s/%04d" % (self.pagename, last_comment_pagename + 1)) + comment_pagename = "%s/%04d" % (self.pagename, last_comment_pagename + 1) + new_page = PageEditor(request, comment_pagename) + username = request.user.name try: - new_page.saveText(comment, 0) + # 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): """ diff -r 7107bc9e7831 -r 6ad31856efbf convert.py --- a/convert.py Sat Nov 02 20:08:45 2013 +0100 +++ b/convert.py Sun Nov 03 00:45:49 2013 +0100 @@ -476,9 +476,13 @@ # Add an ACL to comment pages so that people cannot change other # people's comments. + # NOTE: This should match the PostComment action. if type == "Comment": - text = "#acl %s:read,write,delete,revert All:read\n%s" % (username, text or read(filename)) + text = """\ +#acl %s:read,write,delete,revert All:read +#pragma comment-owner %s +%s""" % (username, username, text or read(filename)) # Add child page information to the content. diff -r 7107bc9e7831 -r 6ad31856efbf css/includecomments.css --- a/css/includecomments.css Sat Nov 02 20:08:45 2013 +0100 +++ b/css/includecomments.css Sun Nov 03 00:45:49 2013 +0100 @@ -16,6 +16,17 @@ padding: 1em; } +.included-comment-owner { + float: left; + clear: left; + margin-right: 1em; + padding: 0.5em; + background-color: #ddd; + color: #000; + font-weight: bold; + font-size: larger; +} + /* Hide the link to the comment form when showing the form. */ #includecomments-anchor:target > a { diff -r 7107bc9e7831 -r 6ad31856efbf macros/IncludeComments.py --- a/macros/IncludeComments.py Sat Nov 02 20:08:45 2013 +0100 +++ b/macros/IncludeComments.py Sun Nov 03 00:45:49 2013 +0100 @@ -4,10 +4,24 @@ @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 + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO Dependencies = ['pages'] @@ -16,14 +30,19 @@ def execute(macro, text): request = macro.request fmt = request.formatter - pagename = request.page.page_name + page = request.page + pagename = page.page_name _ = request.getText - included_content = Include.execute(macro, text or "^%s/" % pagename, included_page_css_class="included-comment") - 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): @@ -46,9 +65,91 @@ """ % 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. - append(included_content) + 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 = StringIO() + request.redirect(strfile) + try: + inc_page.send_page(content_only=True, + omit_footnotes=True, + count_hit=False) + append(strfile.getvalue()) + 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)