1 """
   2     MoinMoin - Modified Include macro
   3 
   4     This macro includes the formatted content of the given page(s). See
   5 
   6         http://purl.net/wiki/moinmaster/HelpOnMacros/Include
   7 
   8     for detailed docs.
   9 
  10     @copyright: 2011      Eric Thrift
  11                 2000-2004 Juergen Hermann <jh@web.de>,
  12                 2000-2001 Richard Jones <richard@bizarsoftware.com.au>
  13     @license: GNU GPL, see COPYING for details.
  14 """
  15 def _getParent(pagename):
  16     """ Return parent of pagename.
  17     """
  18     pos = pagename.rfind('/')
  19     if pos >= 0:
  20         return pagename[:pos]
  21     return None
  22     
  23 Dependencies = ["time"] # works around MoinMoinBugs/TableOfContentsLacksLinks
  24 
  25 generates_headings = True
  26 
  27 import re, StringIO, string, time
  28 from MoinMoin import wikiutil, action
  29 from MoinMoin.Page import Page
  30 from MoinMoin.action import AttachFile
  31 
  32 _sysmsg = '<p><strong class="%s">%s</strong></p>'
  33 
  34 ## keep in sync with TableOfContents macro!
  35 _arg_heading = r'(?P<heading>,)\s*(|(?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))'
  36 _arg_level = r',\s*(?P<level>\d*)'
  37 _arg_from = r'(,\s*from=(?P<fquote>[\'"])(?P<from>.+?)(?P=fquote))?'
  38 _arg_to = r'(,\s*to=(?P<tquote>[\'"])(?P<to>.+?)(?P=tquote))?'
  39 _arg_sort = r'(,\s*sort=(?P<sort>(ascending|descending)))?'
  40 _arg_items = r'(,\s*items=(?P<items>\d+))?'
  41 _arg_skipitems = r'(,\s*skipitems=(?P<skipitems>\d+))?'
  42 _arg_titlesonly = r'(,\s*(?P<titlesonly>titlesonly))?'
  43 _arg_editlink = r'(,\s*(?P<editlink>editlink))?'
  44 _args_re_pattern = r'^(?P<name>[^,]+)(%s(%s)?%s%s%s%s%s%s%s)?$' % (
  45     _arg_heading, _arg_level, _arg_from, _arg_to, _arg_sort, _arg_items,
  46     _arg_skipitems, _arg_titlesonly, _arg_editlink)
  47 
  48 _title_re = r"^(?P<heading>\s*(?P<hmarker>=+)\s.*\s(?P=hmarker))$"
  49 
  50 
  51 def extract_titles(body, title_re):
  52     titles = []
  53     for title, _ in title_re.findall(body):
  54         h = title.strip()
  55         level = 1
  56         while h[level:level+1] == '=':
  57             level += 1
  58         title_text = h[level:-level].strip()
  59         titles.append((title_text, level))
  60     return titles
  61 
  62 def execute(macro, text, args_re=re.compile(_args_re_pattern), title_re=re.compile(_title_re, re.M)):
  63     request = macro.request
  64     _ = request.getText
  65     # return immediately if getting links for the current page
  66     if request.mode_getpagelinks:
  67         return ''
  68 
  69     # parse and check arguments
  70     args = text and args_re.match(text)
  71     if not args:
  72         return (_sysmsg % ('error', _('Invalid include arguments "%s"!')) % (text, ))
  73 
  74     # prepare including page
  75     result = []
  76     print_mode = request.action in ("print", "format")
  77     this_page = macro.formatter.page
  78     if not hasattr(this_page, '_macroInclude_pagelist'):
  79         this_page._macroInclude_pagelist = {}
  80 
  81     # get list of pages to include
  82     inc_name = wikiutil.AbsPageName(this_page.page_name, args.group('name'))
  83     pagelist = [inc_name]
  84     if inc_name.startswith("^"):
  85         try:
  86             inc_match = re.compile(inc_name)
  87         except re.error:
  88             pass # treat as plain page name
  89         else:
  90             # Get user filtered readable page list
  91             pagelist = request.rootpage.getPageList(filter=inc_match.match)
  92     count = len(pagelist)
  93 
  94     # sort and limit page list
  95     pagelist.sort()
  96     sort_dir = args.group('sort')
  97     if sort_dir == 'descending':
  98         pagelist.reverse()
  99 
 100     max_items = 40
 101     maxvar = args.group("items")
 102 
 103     
 104     total = int(count)
 105     
 106 
 107     if maxvar:
 108         max_items = int(maxvar) 
 109 
 110     skipitems = 0
 111     if args.group("skipitems"):
 112         skipitems = int(args.group("skipitems"))
 113 
 114     cur_item = 0
 115 #    pagelist = pagelist[:int(max_items)] # If we filter the list here, the "skipitems" filter will skip over items that should legitimately be included!
 116 
 117     m_skipitems = skipitems # this is the parameter value
 118     enditem = (m_skipitems + max_items)
 119     if enditem > int(count):
 120         enditem = int(count)
 121     startitem = (m_skipitems + 1)
 122     if int(count) == 0:
 123         result.append(_("<b>There are no comments yet on this topic!</b>"))
 124     else:
 125         result.append(_("<b>Showing comments %s - %s of %s</b>") % (str(startitem), str(enditem), str(count)))
 126 
 127     titlesonly = args.group('titlesonly')
 128     editlink = args.group('editlink')
 129     result.append('<table class="forum">')
 130 
 131     # iterate over pages
 132     for inc_name in pagelist:
 133         cur_item += 1
 134         if not request.user.may.read(inc_name):
 135             continue
 136         if inc_name in this_page._macroInclude_pagelist:
 137             result.append(u'<p><strong class="error">Recursive include of "%s" forbidden</strong></p>' % (inc_name, ))
 138             continue
 139         if skipitems:
 140             skipitems -= 1
 141             continue
 142         if cur_item > enditem:
 143             continue
 144         fmt = macro.formatter.__class__(request, is_included=True)
 145         fmt._base_depth = macro.formatter._base_depth
 146         inc_page = Page(request, inc_name, formatter=fmt)
 147         if not inc_page.exists():
 148             continue
 149         inc_page._macroInclude_pagelist = this_page._macroInclude_pagelist
 150 
 151         # check for "from" and "to" arguments (allowing partial includes)
 152         body = inc_page.get_raw_body() + '\n'
 153         from_pos = 0
 154         to_pos = -1
 155         from_re = args.group('from')
 156         if from_re:
 157             try:
 158                 from_match = re.compile(from_re, re.M).search(body)
 159             except re.error:
 160                 ##result.append("*** fe=%s ***" % e)
 161                 from_match = re.compile(re.escape(from_re), re.M).search(body)
 162             if from_match:
 163                 from_pos = from_match.end()
 164             else:
 165                 result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % from_re)
 166         to_re = args.group('to')
 167         if to_re:
 168             try:
 169                 to_match = re.compile(to_re, re.M).search(body, from_pos)
 170             except re.error:
 171                 to_match = re.compile(re.escape(to_re), re.M).search(body, from_pos)
 172             if to_match:
 173                 to_pos = to_match.start()
 174             else:
 175                 result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % to_re)
 176 
 177         if titlesonly:
 178             levelstack = []
 179             for title, level in extract_titles(body[from_pos:to_pos], title_re):
 180                 if levelstack:
 181                     if level > levelstack[-1]:
 182                         result.append(macro.formatter.bullet_list(1))
 183                         levelstack.append(level)
 184                     else:
 185                         while levelstack and level < levelstack[-1]:
 186                             result.append(macro.formatter.bullet_list(0))
 187                             levelstack.pop()
 188                         if not levelstack or level != levelstack[-1]:
 189                             result.append(macro.formatter.bullet_list(1))
 190                             levelstack.append(level)
 191                 else:
 192                     result.append(macro.formatter.bullet_list(1))
 193                     levelstack.append(level)
 194                 result.append(macro.formatter.listitem(1))
 195                 result.append(inc_page.link_to(request, title))
 196                 result.append(macro.formatter.listitem(0))
 197             while levelstack:
 198                 result.append(macro.formatter.bullet_list(0))
 199                 levelstack.pop()
 200             continue
 201 
 202         if from_pos or to_pos != -1:
 203             inc_page.set_raw_body(body[from_pos:to_pos], modified=True)
 204         ##result.append("*** f=%s t=%s ***" % (from_re, to_re))
 205         ##result.append("*** f=%d t=%d ***" % (from_pos, to_pos))
 206 
 207         if not hasattr(request, "_Include_backto"):
 208             request._Include_backto = this_page.page_name
 209 
 210         # do headings
 211         level = None
 212         if args.group('heading') and args.group('hquote'):
 213             heading = args.group('htext') or inc_page.split_title()
 214             level = 1
 215             if args.group('level'):
 216                 level = int(args.group('level'))
 217             if print_mode:
 218                 result.append(macro.formatter.heading(1, level) +
 219                               macro.formatter.text(heading) +
 220                               macro.formatter.heading(0, level))
 221             else:
 222                 url = inc_page.url(request)
 223                 result.extend([
 224                     macro.formatter.heading(1, level, id=heading),
 225                     macro.formatter.url(1, url, css="include-heading-link"),
 226                     macro.formatter.text(heading),
 227                     macro.formatter.url(0),
 228                     macro.formatter.heading(0, level),
 229                 ])
 230 
 231         # set or increment include marker
 232         this_page._macroInclude_pagelist[inc_name] = \
 233             this_page._macroInclude_pagelist.get(inc_name, 0) + 1
 234         # C00000000EricThrift@DornogobiMuseum
 235         
 236         # IMPORTANT! This will fail if the name doesn't match the correct pattern.
 237         m = re.match(r".*/[C]([0-9]*)(([^@]*)@([^@]*))", inc_page.page_name)
 238         post_timestamp = float(int(m.group(1)))
 239         post_timestamp = time.localtime(post_timestamp)
 240         post_time = time.strftime("%c", post_timestamp)
 241         post_editor = m.group(2)
 242         post_editor_name = m.group(3)
 243         post_editor_location = m.group(4)
 244         
 245         '''
 246         # This doesn't work with synchronization since edit log data are lost
 247         
 248         info = inc_page.lastEditInfo()
 249         info2 = inc_page.edit_info()
 250 
 251         editor = string.split(info2['editor'], ":")
 252         editor = editor[-1]
 253                
 254         if editor == "localhost":
 255             editor = "AnonymousUser"
 256         '''
 257         avatarurl = AttachFile.getAttachUrl(post_editor, "avatar.jpg", request)
 258 
 259         result.append('<tr><td class="forumposterinfo">')
 260         result.append('<img src="%s" alt="%s" class="avatar">' % (
 261             wikiutil.escape(avatarurl, 1),
 262             wikiutil.escape("", 1)))
 263         result.append('<span class="editor"><a href="')
 264         result.append(post_editor)
 265         result.append('">')
 266         result.append(post_editor_name)
 267         result.append(" @ ")
 268         result.append(post_editor_location)
 269         result.append("</a></span>")
 270         result.append(post_time)
 271         result.append("<br>")
 272         result.append(inc_page.link_to(request, '[%s]' % (_('permalink'), ), css_class="include-page-link"))
 273 #        result.append("&nbsp;")
 274 #        result.append(inc_page.link_to(request, '[%s]' % (_('edit'), ), css_class="include-edit-link", querystr={'action': 'edit', 'backto': request._Include_backto}))
 275 #                inc_page.link_to(request, '[%s]' % (_('info'), ), css_class="include-info-link", querystr={'action': 'info', 'backto': request._Include_backto}),
 276         result.append("</td><td>")
 277 
 278 
 279 
 280 
 281 
 282         # output the included page
 283         strfile = StringIO.StringIO()
 284         request.redirect(strfile)
 285         try:
 286             inc_page.send_page(content_only=True,
 287                                omit_footnotes=True,
 288                                count_hit=False)
 289             result.append(strfile.getvalue())
 290             result.append("</td></tr>")
 291         finally:
 292             request.redirect()
 293 
 294         # decrement or remove include marker
 295         if this_page._macroInclude_pagelist[inc_name] > 1:
 296             this_page._macroInclude_pagelist[inc_name] = \
 297                 this_page._macroInclude_pagelist[inc_name] - 1
 298         else:
 299             del this_page._macroInclude_pagelist[inc_name]
 300 
 301 
 302     result.append("</table>")
 303     prevskip = (m_skipitems - max_items)
 304     if prevskip < 1:
 305          prevskip = 0
 306     if m_skipitems > 0:
 307 #         result.append('<form method="get" style="display:inline;"><input type="hidden" name="action" value="supplementation" /><input type="hidden" name="skipitems" value="%s" /><input type="hidden" name="items" value="%s" /><input type="submit" value="previous"></form>' % (prevskip, max_items))
 308 
 309          result.append(
 310            this_page.link_to(request, '< %s' % (_('Previous'), ), css_class="prev-link", querystr={'action': 'supplementation', 'skipitems': prevskip, 'items': max_items}),
 311          )
 312          result.append("&nbsp;&nbsp;")
 313          
 314     if enditem < int(count):
 315          result.append(
 316            this_page.link_to(request, '%s >' % (_('Next'), ), css_class="next-link", querystr={'action': 'supplementation', 'skipitems': enditem, 'items': max_items} )
 317          
 318          )
 319 
 320 
 321         # XXX page.link_to is wrong now, it escapes the edit_icon html as it escapes normal text
 322 
 323 
 324     return ''.join(result)
 325 
 326 # vim:ts=4:sw=4:et

There are 0 attachment(s) stored for this page.

MoinMoinCustomizations/IncludeComments.py (last edited 2011-06-22 09:27:30 by EricThrift)