Details

Applies to
Moin 1.8
Purpose

Add multiple templates support to NewPage Macro

Description

The orignal NewPage macro only support one template. If the user want to create a page from multiple templates, user has to write multiple NewPage macro. Tedious and not neatly.

Patch

   1 # Add a dropdown select list for NewPage macro to support multiple template selection.
   2 # Pass categories to NewPage macro, and categories append at the end of new page.
   3 
   4 diff -r 6419f0986299 MoinMoin/PageEditor.py
   5 --- a/MoinMoin/PageEditor.py	Fri Nov 21 23:12:33 2008 +0800
   6 +++ b/MoinMoin/PageEditor.py	Sat Nov 22 15:07:55 2008 +0800
   7 @@ -20,6 +20,7 @@
   8  
   9  
  10  from MoinMoin import caching, config, wikiutil, error
  11 +from MoinMoin import wikiutil2
  12  from MoinMoin.Page import Page
  13  from MoinMoin.widget import html
  14  from MoinMoin.widget.dialog import Status
  15 @@ -426,6 +427,9 @@
  16          lang = self.pi.get('language', request.cfg.language_default)
  17  
  18          request.write("<p>")
  19 +        category = form.get('category',[None])[0] or kw.get('category', None)
  20 +        if category:
  21 +            raw_body = wikiutil2.append_category(request, raw_body, category)
  22          request.write(
  23              u'''\
  24  <textarea id="editor-textarea" name="savetext" lang="%(lang)s" dir="%(dir)s" rows="%(rows)d" cols="80"
  25 diff -r 6419f0986299 MoinMoin/action/edit.py
  26 --- a/MoinMoin/action/edit.py	Fri Nov 21 23:12:33 2008 +0800
  27 +++ b/MoinMoin/action/edit.py	Sat Nov 22 15:07:55 2008 +0800
  28 @@ -8,7 +8,7 @@
  29                  2006 MoinMoin:ThomasWaldmann
  30      @license: GNU GPL, see COPYING for details.
  31  """
  32 -from MoinMoin import wikiutil
  33 +from MoinMoin import wikiutil, wikiutil2
  34  from MoinMoin.Page import Page
  35  
  36  def execute(pagename, request):
  37 @@ -122,30 +122,7 @@
  38      # markup.
  39  
  40      if category and category != _('<No addition>'): # opera 8.5 needs this
  41 -        # strip trailing whitespace
  42 -        savetext = savetext.rstrip()
  43 -
  44 -        # Add category separator if last non-empty line contains
  45 -        # non-categories.
  46 -        lines = [line for line in savetext.splitlines() if line]
  47 -        if lines:
  48 -
  49 -            import re
  50 -            p_strip = re.compile(ur'^(?:[[]"|[[][[])?(.*?)(?:"[]]|[]][]])?$')
  51 -            p_split = re.compile(ur'[[]".+?"[]]|[[][[].+?[]][]]|\S+')
  52 -            categories = map( lambda x: p_strip.search(x).groups()[0],
  53 -                              p_split.findall(lines[-1]))
  54 -
  55 -            if categories:
  56 -                confirmed = wikiutil.filterCategoryPages(request, categories)
  57 -                if len(confirmed) < len(categories):
  58 -                    # This was not a categories line, add separator
  59 -                    savetext += u'\n----\n'
  60 -
  61 -        # Add new category
  62 -        if savetext and savetext[-1] != u'\n':
  63 -            savetext += ' '
  64 -        savetext += category + u'\n' # Should end with newline!
  65 +        savetext = wikiutil2.append_category(request, savetext, category)
  66  
  67      # Preview, spellcheck or spellcheck add new words
  68      if ('button_preview' in request.form or
  69 diff -r 6419f0986299 MoinMoin/action/newpage.py
  70 --- a/MoinMoin/action/newpage.py	Fri Nov 21 23:12:33 2008 +0800
  71 +++ b/MoinMoin/action/newpage.py	Sat Nov 22 15:07:55 2008 +0800
  72 @@ -22,7 +22,51 @@
  73          self.pagename = self.request.form.get('pagename', [None])[0]
  74          self.nametemplate = self.request.form.get('nametemplate', ['%s'])[0]
  75          self.nametemplate = self.nametemplate.replace('\x00', '')
  76 +        self.parent = self.request.form.get('parent', [''])[0]
  77 +        self.template = self.request.form.get('template', [''])[0]
  78 +        self.category = self.request.form.get('category', [None])[0]
  79 +        if ',' in self.template:
  80 +            arg_kw = self.parse_combined_template(self.template)
  81 +            self.template = arg_kw.get('template', "")
  82 +            self.parent = arg_kw.get('parent') or self.parent
  83 +            self.nametemplate = arg_kw.get('nametemplate') or self.nametemplate
  84 +            category = arg_kw.get('category', "")
  85 +            if self.category and category:
  86 +                self.category = ','.join([self.category, category])
  87 +            else:
  88 +                self.category = self.category or category
  89  
  90 +    def parse_combined_template(self, template):
  91 +        kw = {'template':'',
  92 +              'parent':'',
  93 +              'nametemplate':'',
  94 +              'category':'',
  95 +              }
  96 +        if template and ',' in template:
  97 +            for item in template.split(','):
  98 +                item = item.strip()
  99 +                # check if item is template
 100 +                if not kw['template'] and self.request.cfg.cache.page_template_regex.search(item):
 101 +                    kw['template'] = item 
 102 +                # check if item is category
 103 +                elif self.request.cfg.cache.page_category_regexact.search(item):
 104 +                    if kw['category']:
 105 +                        kw['category'] = ','.join([kw['category'], item])
 106 +                    else:
 107 +                        kw['category'] = item
 108 +                # then item is parent or nametemplate
 109 +                elif not kw['parent']:
 110 +                    kw['parent'] = item
 111 +                elif not kw['nametemplate']:
 112 +                    kw['nametemplate'] = item
 113 +                else:
 114 +                    # ignore bad parameters
 115 +                    pass
 116 +        else:
 117 +            kw['template'] = template
 118 +        
 119 +        return kw
 120 +        
 121      def checkAndCombineArguments(self):
 122          """ Check arguments in form, return error msg
 123  
 124 @@ -82,13 +126,14 @@
 125              pagename = self.pagename
 126              query = {'action': 'edit', 'backto': self.referrer}
 127  
 128 -            template = self.request.form.get('template', [''])[0]
 129 -            if template:
 130 -                query['template'] = template
 131 +            if self.template:
 132 +                query['template'] = self.template
 133 +            
 134 +            if self.category:
 135 +                query['category'] = self.category
 136  
 137 -            parent = self.request.form.get('parent', [''])[0]
 138 -            if parent:
 139 -                pagename = "%s/%s" % (parent, pagename)
 140 +            if self.parent:
 141 +                pagename = "%s/%s" % (self.parent, pagename)
 142  
 143              url = Page(self.request, pagename).url(self.request, query)
 144              self.request.http_redirect(url)
 145 diff -r 6419f0986299 MoinMoin/macro/NewPage.py
 146 --- a/MoinMoin/macro/NewPage.py	Fri Nov 21 23:12:33 2008 +0800
 147 +++ b/MoinMoin/macro/NewPage.py	Sat Nov 22 15:07:55 2008 +0800
 148 @@ -25,7 +25,7 @@
 149  
 150      Usage:
 151  
 152 -        <<NewPage(template, buttonLabel, parentPage)>>
 153 +        <<NewPage(template, buttonLabel, parentPage, name_template=u"%s", type=u"select", layout=u"", category=u"")>>
 154  
 155      Examples:
 156  
 157 @@ -39,14 +39,37 @@
 158              Create an input field with button labeled 'Create New
 159              Bug'.  The new page will use the BugTemplate template,
 160              and create the page as a subpage of MoinMoinBugs.
 161 +
 162 +        <<NewPage({u"AbcTemplate":u"Abc",u"XyzTemplate":u"Xyz"},
 163 +            Create,Meetings,%Y-%m-%d_%s, category=u"CategoryX,CategoryY")>>
 164 +
 165 +            User can choose template from a drop down select box.
 166 +            New page name will have the date at the beginning.
 167 +            CategoryX and CategoryY will append at the end of the page.
 168 +
 169 +        <<NewPage({u"AbcTemplate,CategoryX":u"Abc",u"XyzTemplate,CategoryY":u"Xyz",u"XyzTemplate,CategoryY,CategoryZ":u"Xyz2"},
 170 +            Create,Meetings,%Y-%m-%d_%s)>>
 171 +
 172 +            User can choose template from a drop down select box.
 173 +            New page name will have the date at the beginning.
 174 +            CategoryX, CategoryY, or CategoryZ will append at the end of the page.
 175      """
 176  
 177      def __init__(self, macro, template=u'', button_label=u'',
 178 -                 parent_page=u'', name_template=u'%s'):
 179 +                 parent_page=u'', name_template=u'%s', type=u'select', layout=u'', category=u''):
 180          self.macro = macro
 181          self.request = macro.request
 182          self.formatter = macro.formatter
 183 -        self.template = template
 184 +        if isinstance(template, dict):
 185 +            self.template = []
 186 +            for k,v in template.iteritems():
 187 +                self.template.append([v,k])
 188 +            self.template = sorted(self.template)
 189 +            self.template = [ (item[1], item[0]) for item in self.template ]
 190 +        else:
 191 +            self.template = template
 192 +        self.type = type
 193 +        self.layout = layout
 194          _ = self.request.getText
 195          if button_label:
 196              # Try to get a translation, this will probably not work in
 197 @@ -66,6 +89,7 @@
 198          else:
 199              self.parent = parent_page
 200          self.nametemplate = name_template
 201 +        self.category = category
 202  
 203      def renderInPage(self):
 204          """ Render macro in page context
 205 @@ -77,7 +101,16 @@
 206          _ = self.request.getText
 207  
 208          requires_input = '%s' in self.nametemplate
 209 -
 210 +        if not self.layout:
 211 +            self.layout = """
 212 +<table class="borderless">
 213 +  <tr>
 214 +    <td>""" + _("Input title: ") + """</td><td>%(input)s</td></tr>
 215 +  <tr>
 216 +    <td>""" + _("Select template: ") + """</td><td>%(select)s</td></tr>
 217 +  <tr><td colspan="2" align="right">%(button)s</td></tr>
 218 +</table>
 219 +"""
 220  
 221          # TODO: better abstract this using the formatter
 222          # OSSXP: self.request.page.page_name and self.formatter.page.page_name may different, 
 223 @@ -91,26 +124,82 @@
 224                  except:
 225                      self.parent = self.formatter.page.page_name
 226              
 227 -        html = [
 228 +        header = [
 229              u'<form class="macro" method="POST" action="%s/%s"><div>' % (self.request.getScriptname(), wikiutil.quoteWikinameURL(self.formatter.page.page_name)),
 230              u'<input type="hidden" name="action" value="newpage">',
 231              u'<input type="hidden" name="parent" value="%s">' % wikiutil.escape(self.parent, 1),
 232 -            u'<input type="hidden" name="template" value="%s">' % wikiutil.escape(self.template, 1),
 233 +            u'<input type="hidden" name="category" value="%s">' % wikiutil.escape(self.category, 1),
 234              u'<input type="hidden" name="nametemplate" value="%s">' % wikiutil.escape(self.nametemplate, 1),
 235          ]
 236 +        header = '\n'.join(header)
 237 +        footer = u'</div></form>'
 238 +        button = u'<input type="submit" value="%s">' % wikiutil.escape(self.label, 1)
 239 +        
 240 +        select = u''
 241 +        if self.template:
 242 +            if isinstance(self.template, basestring):
 243 +                select = u''
 244 +                header += u'\n<input type="hidden" name="template" value="%s">' % wikiutil.escape(self.template, 1)
 245 +            elif isinstance(self.template, (list,tuple)):
 246 +                select = []
 247 +                if self.type == "select":
 248 +                    select.append(u'<select name="template" size="0">')
 249 +                for item in self.template:
 250 +                    if isinstance(item, basestring):
 251 +                        k=item
 252 +                        v=item
 253 +                    else:
 254 +                        k=item[0]
 255 +                        v=item[1]
 256 +                    if self.type == "select":
 257 +                        select.append(u'<option value="%(key)s" label="%(value)s">%(value)s</option>' % \
 258 +                                      {'key':wikiutil.escape(k,1), 'value':wikiutil.escape(v,1)})
 259 +                    else: # type == radio
 260 +                        select.append(u'<input type="radio" name="template" value="%(key)s">%(value)s' % \
 261 +                                      {'key':wikiutil.escape(k,1), 'value':wikiutil.escape(v,1)})
 262 +                if self.type == "select":
 263 +                    select.append(u'</select>')
 264 +                select = '\n'.join(select)
 265 +        if requires_input:
 266 +            input = u'<input type="text" name="pagename" size="30">'
 267 +        else:
 268 +            input = u''
 269 +        
 270 +        if input and select and self.layout:
 271 +            html = '\n'.join([header,
 272 +                              self.layout % {'button': button, 'select':select, 'input':input},
 273 +                              footer])
 274 +        else:
 275 +            html = '\n'.join([header, select, input, button,footer])
 276  
 277 -        if requires_input:
 278 -            html += [
 279 -                u'<input type="text" name="pagename" size="30">',
 280 -            ]
 281 -        html += [
 282 -            u'<input type="submit" value="%s">' % wikiutil.escape(self.label, 1),
 283 -            u'</div></form>',
 284 -            ]
 285 -        return self.formatter.rawHTML('\n'.join(html))
 286 +        return self.formatter.rawHTML(html)
 287  
 288 -def macro_NewPage(macro, template=u'', button_label=u'',
 289 -                  parent_page=u'', name_template=u'%s'):
 290 +
 291 +def execute(macro, args):
 292      """ Temporary glue code to use with moin current macro system """
 293 -    return NewPage(macro, template, button_label, parent_page, name_template).renderInPage()
 294 +    request = macro.request
 295 +    import re
 296 +    pattern = re.compile(ur"""
 297 +^(?P<template>
 298 +      \[.*?\] # list
 299 +    |
 300 +      \(.*?\) # tuple
 301 +    |
 302 +      \{.*?\} # dict
 303 +    |
 304 +      (?P<mark>"').*?(?P=mark) # string with mark
 305 +    |
 306 +      [^,]* # string without mark
 307 +),?(?P<args>.*)$    # others arguments
 308 +""", re.UNICODE|re.VERBOSE)
 309 +    template = ""
 310 +    if args:
 311 +        match = pattern.search(args)
 312 +        if match:
 313 +            template = match.group('template')
 314 +            args = match.group('args')
 315 +            if template:
 316 +                if template[0] in '[({\'"':
 317 +                    template = eval(template)
 318  
 319 +    return wikiutil.invoke_extension_function(request, NewPage, args, fixed_args=[macro, template]).renderInPage()
 320 diff -r 6419f0986299 MoinMoin/wikiutil2.py
 321 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
 322 +++ b/MoinMoin/wikiutil2.py	Sat Nov 22 15:07:55 2008 +0800
 323 @@ -0,0 +1,68 @@
 324 +# -*- coding: utf-8 -*-
 325 +"""
 326 +    MoinMoin - Wiki Extra Utility Functions
 327 +
 328 +    @copyright: 2008 Jiang Xin <worldhello.net@gmail.com>
 329 +    @license: GNU GPL, see COPYING for details.
 330 +"""
 331 +
 332 +import re
 333 +from MoinMoin import wikiutil
 334 +
 335 +from MoinMoin import log
 336 +logging = log.getLogger(__name__)
 337 +
 338 +
 339 +def append_category(request, raw_body, category):
 340 +    """
 341 +    Append category at the end of raw_body
 342 +    """
 343 +    _ = request.getText
 344 +    
 345 +    # user can input multiple categories, separate by ';'
 346 +    categorylist = []
 347 +
 348 +    if isinstance(category, (list,tuple)):
 349 +        categorylist = category
 350 +    elif isinstance(category, basestring):
 351 +        for cat in category.split(','):
 352 +            if cat.startswith("[["):
 353 +                cat = cat[2:-2]
 354 +            if request.cfg.cache.page_category_regexact.search(cat):
 355 +                if cat not in categorylist:
 356 +                    categorylist.append(cat)
 357 +
 358 +    # no valid category, return raw_body
 359 +    if not categorylist or not raw_body:
 360 +        return raw_body
 361 +
 362 +    # strip trailing whitespace
 363 +    raw_body = raw_body.rstrip()
 364 +
 365 +    lines = [line for line in raw_body.splitlines() if line]
 366 +    p_strip = re.compile(ur'^(?:[[]"|[[][[])?(.*?)(?:"[]]|[]][]])?$')
 367 +    p_split = re.compile(ur'[[]".+?"[]]|[[][[].+?[]][]]|\S+')
 368 +    categories = map( lambda x: p_strip.search(x).groups()[0],
 369 +                      p_split.findall(lines[-1]))
 370 +    if categories:
 371 +        confirmed = wikiutil.filterCategoryPages(request, categories)
 372 +        if len(confirmed) < len(categories):
 373 +            # This was not a categories line, add separator
 374 +            categories = []
 375 +
 376 +    # Add category separator if last non-empty line contains non-categories.
 377 +    if not categories:
 378 +        raw_body += u'\n\n----\n'
 379 +    
 380 +    for cat in categorylist:
 381 +        if cat not in categories:
 382 +            # Add new category
 383 +            if raw_body and raw_body[-1] != u'\n':
 384 +                raw_body += ' '
 385 +            raw_body += wikiutil.pagelinkmarkup(cat)
 386 +
 387 +    if raw_body and raw_body[-1] != u'\n':
 388 +        raw_body += u'\n' # Should end with newline!
 389 +
 390 +    return raw_body
 391 +
 392 
30470_multi_templates_and_categories_for_newpage_macro.patch

Example

http://pysvnmanager.ossxp.com/NewPageWithMultiTemplatesSupport

Discussion

Plan


CategoryMoinMoinPatch

MoinMoin: MoinMoinPatch/MultipleTemplatesSupportForNewPageMaro (last edited 2008-11-26 08:27:20 by JiangXin)