Changeset 2797

Show
Ignore:
Timestamp:
11/18/07 01:03:42 (1 year ago)
Author:
osimons
Message:

AddCommentMacro: 0.11 version working.

  • Uses new context / resource APIs from current Trac 0.11dev
  • Uses genshi to build the html
  • Depends on MacroPostPlugin for 0.11 (v 0.2)
  • Various minor fixes

More details on ticket #1835.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • addcommentmacro/0.11/addcomment/macro.py

    r2097 r2797  
    11# vim: expandtab 
     2import re, time 
     3from StringIO import StringIO 
     4 
     5from genshi.builder import tag 
     6 
    27from trac.core import * 
     8from trac.wiki.formatter import format_to_html 
     9from trac.util import TracError 
     10from trac.util.text import to_unicode 
     11from trac.web.chrome import add_link, add_script 
     12from trac.wiki.api import parse_args 
    313from trac.wiki.macros import WikiMacroBase 
     14from trac.wiki.model import WikiPage 
    415 
    5 import trac.perm 
    6 from StringIO import StringIO 
    7 from trac.wiki.formatter import wiki_to_html 
    8 from trac.wiki.model import WikiPage 
    9 from trac.util import Markup 
    10 from trac.util import TracError 
    11 from trac.web.chrome import add_link 
    12 from trac.util.text import to_unicode 
    13  
    14 import re, time 
    1516 
    1617class AddCommentMacro(WikiMacroBase): 
    17     """A macro to add comments to a page.""" 
     18    """A macro to add comments to a page. Usage: 
     19    {{{ 
     20    [[AddComment]] 
     21    }}} 
     22    The macro accepts one optional argument that allows appending 
     23    to the wiki page even though user may not have modify permission: 
     24    {{{ 
     25    [[AddComment(appendonly)]] 
     26    }}} 
     27    """ 
    1828     
    19     def render_macro(self, req, name, content): 
    20         return execute(req.hdf, content, self.env) 
     29    def expand_macro(self, formatter, name, content): 
     30         
     31        args, kw = parse_args(content) 
     32        req = formatter.req 
     33        context = formatter.context 
     34         
     35        # Prevent multiple inclusions - store a temp in req 
     36        if hasattr(req, 'addcommentmacro'): 
     37            raise TracError('\'AddComment\' macro cannot be included twice.') 
     38        req.addcommentmacro = True 
     39         
     40        # Prevent it being used outside of wiki page context 
     41        resource = context.resource 
     42        if not resource.realm == 'wiki': 
     43            raise TracError('\'AddComment\' macro can only be used in Wiki pages.') 
     44         
     45        # Setup info and defaults 
     46        authname = req.authname 
     47        page = WikiPage(self.env, resource) 
     48        page_url = req.href.wiki(resource.id) 
     49        wikipreview = req.args.get("preview", "") 
     50        appendonly = ('appendonly' in args) 
     51        # Can this user add a comment to this page? 
     52        cancomment = not page.readonly 
     53        # Is this an "append-only" comment or are we an administrator? 
     54        if 'WIKI_ADMIN' in req.perm(resource) or appendonly: 
     55            cancomment = True 
     56        if not cancomment: 
     57            raise TracError('Error: Insufficient privileges to AddComment') 
     58        disabled = False 
     59         
     60        # Get the data from the POST 
     61        comment = req.args.get("addcomment", "") 
     62        preview = req.args.get("previewaddcomment", "") 
     63        cancel = req.args.get("canceladdcomment", "") 
     64        submit = req.args.get("submitaddcomment", "") 
     65        if not cancel and req.authname == 'anonymous': 
     66            authname = req.args.get("authoraddcomment", authname) 
     67         
     68        # Ensure [[AddComment]] is not present in comment, so that infinite 
     69        # recursion does not occur. 
     70        comment = to_unicode(re.sub('(^|[^!])(\[\[AddComment)', '\\1!\\2', comment)) 
     71         
     72        the_preview = the_message = the_form = tag() 
     73         
     74        if wikipreview or not ('WIKI_MODIFY' in req.perm(resource) or appendonly): 
     75            disabled = True 
     76         
     77        # If we are submitting or previewing, inject comment as it should look 
     78        if cancomment and comment and (preview or submit): 
     79            heading = tag.h4("Comment by ", authname, " on ", 
     80                        to_unicode(time.strftime('%c', time.localtime())), 
     81                        id="commentpreview") 
     82            if preview: 
     83                the_preview = tag.div(heading, 
     84                                format_to_html(self.env, context, comment), 
     85                                class_="wikipage", id="preview") 
     86         
     87        # When submitting, inject comment before macro 
     88        if comment and submit: 
     89            submitted = False 
     90            newtext = "" 
     91            for line in page.text.splitlines(): 
     92                if line.find('[[AddComment') == 0: 
     93                    newtext += "==== Comment by %s on %s ====\n%s\n\n" % ( 
     94                            authname, 
     95                            to_unicode(time.strftime('%c', time.localtime())), 
     96                            comment) 
     97                    submitted = True 
     98                newtext += line+"\n" 
     99            if submitted: 
     100                page.text = newtext 
     101                page.save(authname, 'Comment added', req.environ['REMOTE_ADDR']) 
     102                req.warning("Comment saved.") 
     103                req.redirect(page_url) 
     104            else: 
     105                the_message = tag.div(tag.strong("ERROR: "), "[[AddComment]] " 
     106                          "macro call must be the only content on its line. " 
     107                          "Could not add comment.", 
     108                          class_="system-message") 
    21109 
    22     def _render_macro(self, req, name, content): 
    23         pass # Fill in a deuglified version here 
     110        the_form = tag.form( 
     111                    tag.fieldset( 
     112                        tag.legend("Add comment"), 
     113                        tag.div( 
     114                            (wikipreview and "Page preview..." or None), 
     115                            tag.textarea((not cancel and comment or ""), 
     116                                        class_="wikitext", 
     117                                        id="addcomment", 
     118                                        name="addcomment", 
     119                                        cols=80, rows=5, 
     120                                        disabled=(disabled and "disabled" or None)), 
     121                            class_="field" 
     122                        ), 
     123                        (req.authname == 'anonymous' and tag.div( 
     124                            tag.label("Your email or username:", 
     125                                    for_="authoraddcomment"), 
     126                            tag.input(id="authoraddcomment", type="text", 
     127                                    size=30, value=authname) 
     128                        ) or None), 
     129                        tag.div( 
     130                            tag.input(value="Add comment", type="submit", 
     131                                    name="submitaddcomment", size=30, 
     132                                    disabled=(disabled and "disabled" or None)), 
     133                            tag.input(value="Preview comment", type="submit", 
     134                                    name="previewaddcomment", 
     135                                    disabled=(disabled and "disabled" or None)), 
     136                            tag.input(value="Cancel", type="submit", 
     137                                    name="canceladdcomment", 
     138                                    disabled=(disabled and "disabled" or None)), 
     139                            class_="buttons" 
     140                        ), 
     141                    ), 
     142                    method="post", 
     143                    action=page_url+"#commenting", 
     144                ) 
     145         
     146        add_script(req, 'common/js/wikitoolbar.js') 
    24147 
     148        return tag.div(the_preview, the_message, the_form, id="commenting") 
     149     
    25150    def process_macro_post(self, req): 
    26151        self.log.debug('AddCommentMacro: Got a POST') 
    27          
    28 def execute(hdf, args, env): 
    29     # prevents from multiple inclusions 
    30     if hdf.has_key('addcommentmacro'): 
    31        raise TracError('\'AddComment\' macro cannot be included twice') 
    32     hdf['addcommentmacro'] = True 
    33152 
    34     authname = hdf.getValue("trac.authname", "anonymous") 
    35     db = env.get_db_cnx() 
    36     perm = trac.perm.PermissionCache(env, authname) 
    37     pagename = hdf.getValue("wiki.page_name", "WikiStart") 
    38     page = WikiPage(env, pagename, None, db) 
    39     wikipreview = hdf.getValue("wiki.preview", "") 
    40     appendonly = (args == 'appendonly') 
    41     readonlypage = int(hdf.getValue("wiki.readonly", "0")) 
    42     # Can this user add a comment to this page? 
    43     cancomment = not readonlypage 
    44     # Is this an "append-only" comment or are we an administrator? 
    45     if perm.has_permission('WIKI_ADMIN') or appendonly: 
    46         cancomment = True 
    47  
    48     if not cancomment: 
    49         raise TracError('Error: Insufficient privileges to AddComment') 
    50  
    51     disabled = '' 
    52  
    53     comment = Markup(to_unicode(hdf.getValue("args.addcomment", ""))).unescape() 
    54     preview = hdf.getValue("args.previewaddcomment", "") 
    55     cancel = hdf.getValue("args.canceladdcomment", "") 
    56     submit = hdf.getValue("args.submitaddcomment", "") 
    57     if not cancel: 
    58         authname = hdf.getValue("args.authoraddcomment", authname) 
    59  
    60     # Ensure [[AddComment]] is not present in comment, so that infinite 
    61     # recursion does not occur. 
    62     comment = re.sub('(^|[^!])(\[\[AddComment)', '\\1!\\2', comment) 
    63  
    64     out = StringIO() 
    65     if wikipreview or not (perm.has_permission('WIKI_MODIFY') or appendonly): 
    66         disabled = ' disabled="disabled"' 
    67  
    68     # If we are submitting or previewing, inject comment as it should look 
    69     if cancomment and comment and (preview or submit): 
    70         if preview: 
    71             out.write("<div class='wikipage' id='preview'>\n") 
    72         out.write("<h4 id='commentpreview'>Comment by %s on %s</h4>\n<p>\n%s\n</p>\n" % (authname, time.strftime('%c', time.localtime()), wiki_to_html(comment, env, None))) 
    73         if preview: 
    74             out.write("</div>\n") 
    75  
    76     # When submitting, inject comment before macro 
    77     if comment and submit: 
    78         submitted = False 
    79         newtext = StringIO() 
    80         for line in page.text.splitlines(): 
    81             if line.find('[[AddComment') == 0: 
    82                 newtext.write("==== Comment by %s on %s ====\n%s\n\n" % (authname, time.strftime('%c', time.localtime()), comment)) 
    83                 submitted = True 
    84             newtext.write(line + "\n") 
    85         if submitted: 
    86             # XXX Is this the dodgiest hack ever? This is needed in  
    87             # "appendonly" mode when the page is readonly. XXX 
    88 #            if appendonly: 
    89 #                perm.expand_meta_permission('WIKI_ADMIN'); 
    90             # TODO: How do we get remote_addr from a macro? 
    91             page.text = newtext.getvalue() 
    92             page.save(authname, 'Comment added', None) 
    93             comment = "" 
    94         else: 
    95             out.write("<div class='system-message'><strong>ERROR: [[AddComment]] macro call must be the only content on its line. Could not add comment.</strong></div>\n") 
    96  
    97     out.write("<form action='%s#commentpreview' method='post'>\n" % env.href.wiki(pagename)) 
    98     out.write("<fieldset>\n<legend>Add comment</legend>\n") 
    99     out.write("<div class='field'>\n<textarea class='wikitext' id='addcomment' name='addcomment' cols='80' rows='5'%s>" % disabled) 
    100     if wikipreview: 
    101         out.write("Page preview...") 
    102     elif not cancel: 
    103         out.write(comment) 
    104     out.write("</textarea>\n") 
    105     out.write("</div>\n") 
    106     out.write('<div class="field">\n<label for="authoraddcomment">Your email or username:</label>\n<br/><input id="authoraddcomment" type="text" name="authoraddcomment" size="30" value="%s" />\n</div>' % authname) 
    107     out.write("<div class='field'>\n<input size='30' type='submit' name='submitaddcomment' value='Add comment'%s/>\n" % disabled) 
    108     out.write("<input type='submit' name='previewaddcomment' value='Preview comment'%s/>\n" % disabled) 
    109     out.write("<input type='submit' name='canceladdcomment' value='Cancel'%s/>\n</div>\n" % disabled) 
    110     out.write('<script type="text/javascript" src="%sjs/wikitoolbar.js"></script>' % hdf['htdocs_location']) 
    111     out.write("</fieldset>\n</form>\n") 
    112  
    113     return out.getvalue()# + "<pre>" + hdf.dump() + "</pre>" 
    114  
  • addcommentmacro/0.11/setup.py

    r2098 r2797  
    66setup( 
    77    name = 'TracAddCommentMacro', 
    8     version = '0.2', 
     8    version = '0.3', 
    99    packages = ['addcomment'], 
    1010    package_data={ 'addcomment' : [  ] }, 
     
    2424    }, 
    2525 
    26     install_requires = [ 'TracMacroPost' ], 
     26    install_requires = [ 'TracMacroPost>=0.2' ], 
    2727)