changeset 5102:9ae242080889

drawings/attachments: made editing support more generic (details see below) refactored AttachFile.getAttachUrl: * removed drawing param * it detects drawings now from the filename's extension (e.g. .adraw for the anywikidraw container and .tdraw for the twikidraw container) * it returns None now, if the combination of filename (extension) and do=something is not supported AttachFile.get_action looks up the action (module name) for specific combinations of filenames (extension) and do=subaction. info/history and AttachFile filelist action: Less hardcoded drawing support, it now just tries to get a do=modify URL for every file attachment. If that works, there will be an edit link for that attachment. action.anywikidraw and action.twikidraw: * they get the full container filename now and also use them in UI * they call do=modify to invoke the drawing applet multiconfig: removed drawing_action text_moin_wiki parser: use wikiutil.drawing2fname to process the given drawing name. if it looks like fully qualified (e.g. foo.tdraw, foo.adraw, foo.svg, foo.png, ...), then keep it. otherwise (e.g. foo, foo.bar, ...) append .tdraw as default drawing filename extension to be backwards compatible.
author Thomas Waldmann <tw AT waldmann-edv DOT de>
date Sun, 13 Sep 2009 16:01:09 +0200
parents d8ccac2f24c5
children 6c620a7e2def
files MoinMoin/action/AttachFile.py MoinMoin/action/anywikidraw.py MoinMoin/action/info.py MoinMoin/action/twikidraw.py MoinMoin/config/multiconfig.py MoinMoin/formatter/text_gedit.py MoinMoin/formatter/text_html.py MoinMoin/parser/text_moin_wiki.py MoinMoin/wikiutil.py docs/CHANGES
diffstat 10 files changed, 127 insertions(+), 70 deletions(-) [+]
line wrap: on
line diff
--- a/MoinMoin/action/AttachFile.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/action/AttachFile.py	Sun Sep 13 16:01:09 2009 +0200
@@ -82,15 +82,47 @@
     else:
         return u"/".join(pieces[:-1]), pieces[-1]
 
-def getAttachUrl(pagename, filename, request, addts=0, do='get', drawing=''):
+
+def get_action(request, filename, do):
+    ext_mapping = {
+        # file extension -> do -> action
+        '.tdraw': {
+            'modify': 'twikidraw',
+        },
+        '.adraw': {
+            'modify': 'anywikidraw',
+        },
+    }
+    generic_do_mapping = {
+        # do -> action
+        'get': action_name,
+        'view': action_name,
+        'move': action_name,
+        'del': action_name,
+        'unzip': action_name,
+        'install': action_name,
+        'upload_form': action_name,
+    }
+    basename, ext = os.path.splitext(filename)
+    do_mapping = ext_mapping.get(ext, {})
+    action = do_mapping.get(do, None)
+    if action is None:
+        # we have no special support for this,
+        # look up whether we have generic support:
+        action = generic_do_mapping.get(do, None)
+    return action
+
+
+def getAttachUrl(pagename, filename, request, addts=0, do='get'):
     """ Get URL that points to attachment `filename` of page `pagename`.
-        For upload url (files, not drawings), call with do='upload_form'.
+        For upload url, call with do='upload_form'.
+        Returns the URL to do the specified "do" action or None,
+        if this action is not supported.
     """
-    if not drawing:
-        url = request.href(pagename, action=action_name, do=do, target=filename)
-    else:
-        url = request.href(pagename, action=request.cfg.drawing_action, target=drawing)
-    return url
+    action = get_action(request, filename, do)
+    if action:
+        url = request.href(pagename, action=action, do=do, target=filename)
+        return url
 
 
 def getIndicator(request, pagename):
@@ -281,6 +313,10 @@
         label_unzip = _("unzip")
         label_install = _("install")
 
+        may_read = request.user.may.read(pagename)
+        may_write = request.user.may.write(pagename)
+        may_delete = request.user.may.delete(pagename)
+
         html.append(fmt.bullet_list(1))
         for file in files:
             mt = wikiutil.MimeType(filename=file)
@@ -293,7 +329,6 @@
                        }
 
             links = []
-            may_delete = request.user.may.delete(pagename)
             if may_delete and not readonly:
                 links.append(fmt.url(1, getAttachUrl(pagename, file, request, do='del')) +
                              fmt.text(label_del) +
@@ -308,18 +343,16 @@
                          fmt.text(label_get) +
                          fmt.url(0))
 
-            if ext == '.tdraw':
-                links.append(fmt.url(1, getAttachUrl(pagename, file, request, drawing=base)) +
-                             fmt.text(label_edit) +
-                             fmt.url(0))
-            elif ext == '.adraw':
-                links.append(fmt.url(1, getAttachUrl(pagename, file, request, drawing=base)) +
-                             fmt.text(label_edit) +
-                             fmt.url(0))
-            else:
-                links.append(fmt.url(1, getAttachUrl(pagename, file, request, do='view')) +
-                             fmt.text(label_view) +
-                             fmt.url(0))
+            links.append(fmt.url(1, getAttachUrl(pagename, file, request, do='view')) +
+                         fmt.text(label_view) +
+                         fmt.url(0))
+
+            if may_write and not readonly:
+                edit_url = getAttachUrl(pagename, file, request, do='modify')
+                if edit_url:
+                    links.append(fmt.url(1, edit_url) +
+                                 fmt.text(label_edit) +
+                                 fmt.url(0))
 
             try:
                 is_zipfile = zipfile.is_zipfile(fullpath)
@@ -330,9 +363,7 @@
                                      fmt.text(label_install) +
                                      fmt.url(0))
                     elif (not is_package and mt.minor == 'zip' and
-                          may_delete and
-                          request.user.may.read(pagename) and
-                          request.user.may.write(pagename)):
+                          may_read and may_write and may_delete):
                         links.append(fmt.url(1, getAttachUrl(pagename, file, request, do='unzip')) +
                                      fmt.text(label_unzip) +
                                      fmt.url(0))
--- a/MoinMoin/action/anywikidraw.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/action/anywikidraw.py	Sun Sep 13 16:01:09 2009 +0200
@@ -43,11 +43,11 @@
     # we force the title here, needed later for html>wiki converter
     kw['title'] = "drawing:%s" % wikiutil.quoteWikinameURL(url)
     pagename, drawing = AttachFile.absoluteName(url, self.page.page_name)
-    containername = wikiutil.taintfilename(drawing) + ".adraw"
-    drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request, drawing=drawing)
+    containername = wikiutil.taintfilename(drawing)
+    drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request)
     ci = AttachFile.ContainerItem(self.request, pagename, containername)
     if not ci.exists():
-        title = _('Create new drawing "%(filename)s (opens in new window)"') % {'filename': drawing}
+        title = _('Create new drawing "%(filename)s (opens in new window)"') % {'filename': containername}
         img = self.icon('attachimg')  # TODO: we need a new "drawimg" in similar grey style and size
         css = 'nonexistent'
         return self.url(1, drawing_url, css=css, title=title) + img + self.url(0)
@@ -59,17 +59,17 @@
     # XXX text arg is unused!
     _ = self.request.getText
     pagename, drawing = AttachFile.absoluteName(url, self.page.page_name)
-    containername = wikiutil.taintfilename(drawing) + ".adraw"
+    containername = wikiutil.taintfilename(drawing)
 
-    drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request, drawing=drawing)
+    drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request, do='modify')
     ci = AttachFile.ContainerItem(self.request, pagename, containername)
     if not ci.exists():
-        title = _('Create new drawing "%(filename)s (opens in new window)"') % {'filename': drawing}
+        title = _('Create new drawing "%(filename)s (opens in new window)"') % {'filename': self.text(containername)}
         img = self.icon('attachimg')  # TODO: we need a new "drawimg" in similar grey style and size
         css = 'nonexistent'
         return self.url(1, drawing_url, css=css, title=title) + img + self.url(0)
 
-    title = _('Edit drawing %(filename)s (opens in new window)') % {'filename': self.text(drawing)}
+    title = _('Edit drawing %(filename)s (opens in new window)') % {'filename': self.text(containername)}
     kw['src'] = src = ci.member_url('drawing.png')
     kw['css'] = 'drawing'
 
@@ -88,7 +88,7 @@
         map = map.replace(u'name="%s.svg"' % drawing, u'name="%s"' % mapid)
         # unxml, because 4.01 concrete will not validate />
         map = map.replace(u'/>', u'>')
-        title = _('Clickable drawing: %(filename)s') % {'filename': self.text(drawing)}
+        title = _('Clickable drawing: %(filename)s') % {'filename': self.text(containername)}
         if 'title' not in kw:
             kw['title'] = title
         if 'alt' not in kw:
@@ -132,11 +132,11 @@
         basepath, basename = os.path.split(filename)
         basename, ext = os.path.splitext(basename)
 
-        ci = AttachFile.ContainerItem(request, pagename, target + '.adraw')
+        ci = AttachFile.ContainerItem(request, pagename, target)
         filecontent = file_upload.stream
         content_length = None
         if ext == '.svg': # AnyWikiDraw POSTs this first
-            AttachFile._addLogEntry(request, 'ATTDRW', pagename, target + '.adraw')
+            AttachFile._addLogEntry(request, 'ATTDRW', pagename, target)
             ci.truncate()
             filecontent = filecontent.read() # read file completely into memory
             filecontent = filecontent.replace("\r", "")
@@ -160,7 +160,7 @@
         request = self.request
         pagename = self.pagename
         target = self.target
-        ci = AttachFile.ContainerItem(request, pagename, target + '.adraw')
+        ci = AttachFile.ContainerItem(request, pagename, target)
         if ci.exists():
             drawurl = ci.member_url('drawing.svg')
         else:
--- a/MoinMoin/action/info.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/action/info.py	Sun Sep 13 16:01:09 2009 +0200
@@ -13,6 +13,7 @@
 from MoinMoin.Page import Page
 from MoinMoin.logfile import editlog
 from MoinMoin.widget import html
+from MoinMoin.action import AttachFile
 
 def execute(pagename, request):
     """ show misc. infos about a page """
@@ -101,6 +102,16 @@
             kw.update(dict(rel='nofollow'))
             return page.link_to(request, text, querystr=query, **kw)
 
+        def render_file_action(text, pagename, filename, request, do):
+            url = AttachFile.getAttachUrl(pagename, filename, request, do=do)
+            if url:
+                f = request.formatter
+                link = f.url(1, url) + f.text(text) + f.url(0)
+                return link
+
+        may_write = request.user.may.write(pagename)
+        may_delete = request.user.may.delete(pagename)
+
         # read in the complete log of this page
         log = editlog.EditLog(request, rootpagename=pagename)
         count = 0
@@ -135,25 +146,16 @@
 
                 filename = wikiutil.url_unquote(line.extra)
                 comment = "%s: %s %s" % (line.action, filename, line.comment)
-                size = 0
-                if line.action != 'ATTDEL':
-                    from MoinMoin.action import AttachFile
-                    if AttachFile.exists(request, pagename, filename):
-                        size = AttachFile.size(request, pagename, filename)
-                    if line.action == 'ATTNEW':
-                        actions.append(render_action(_('view'), {'action': 'AttachFile', 'do': 'view', 'target': '%s' % filename}))
-                    elif line.action == 'ATTDRW':
-                        if filename.endswith('.tdraw'):
-                            action = 'twikidraw'
-                            target = filename[:-6]
-                        elif filename.endswith('.adraw'):
-                            action = 'anywikidraw'
-                            target = filename[:-6]
-                        actions.append(render_action(_('edit'), dict(action=action, target=target)))
-
-                    actions.append(render_action(_('get'), {'action': 'AttachFile', 'do': 'get', 'target': '%s' % filename}))
-                    if request.user.may.delete(pagename):
-                        actions.append(render_action(_('del'), {'action': 'AttachFile', 'do': 'del', 'target': '%s' % filename}))
+                if AttachFile.exists(request, pagename, filename):
+                    size = AttachFile.size(request, pagename, filename)
+                    actions.append(render_file_action(_('view'), pagename, filename, request, do='view'))
+                    actions.append(render_file_action(_('get'), pagename, filename, request, do='get'))
+                    if may_delete:
+                        actions.append(render_file_action(_('del'), pagename, filename, request, do='del'))
+                    if may_write:
+                        actions.append(render_file_action(_('edit'), pagename, filename, request, do='modify'))
+                else:
+                    size = 0
 
             history.addRow((
                 rev,
@@ -162,7 +164,7 @@
                 diff,
                 line.getEditor(request) or _("N/A"),
                 wikiutil.escape(comment) or '&nbsp;',
-                "&nbsp;".join(actions),
+                "&nbsp;".join(a for a in actions if a),
             ))
             count += 1
             if count >= max_count:
--- a/MoinMoin/action/twikidraw.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/action/twikidraw.py	Sun Sep 13 16:01:09 2009 +0200
@@ -45,8 +45,8 @@
     # we force the title here, needed later for html>wiki converter
     kw['title'] = "drawing:%s" % wikiutil.quoteWikinameURL(url)
     pagename, drawing = AttachFile.absoluteName(url, self.page.page_name)
-    containername = wikiutil.taintfilename(drawing) + ".tdraw"
-    drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request, drawing=drawing)
+    containername = wikiutil.taintfilename(drawing)
+    drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request)
     ci = AttachFile.ContainerItem(self.request, pagename, containername)
     if not ci.exists():
         title = _('Create new drawing "%(filename)s (opens in new window)"') % {'filename': drawing}
@@ -61,9 +61,9 @@
     # XXX text arg is unused!
     _ = self.request.getText
     pagename, drawing = AttachFile.absoluteName(url, self.page.page_name)
-    containername = wikiutil.taintfilename(drawing) + ".tdraw"
+    containername = wikiutil.taintfilename(drawing)
 
-    drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request, drawing=drawing)
+    drawing_url = AttachFile.getAttachUrl(pagename, containername, self.request, do='modify')
     ci = AttachFile.ContainerItem(self.request, pagename, containername)
     if not ci.exists():
         title = _('Create new drawing "%(filename)s (opens in new window)"') % {'filename': drawing}
@@ -139,11 +139,11 @@
         filename = request.form['filename']
         basepath, basename = os.path.split(filename)
         basename, ext = os.path.splitext(basename)
-        ci = AttachFile.ContainerItem(request, pagename, target + '.tdraw')
+        ci = AttachFile.ContainerItem(request, pagename, target)
         filecontent = file_upload.stream
         content_length = None
         if ext == '.draw': # TWikiDraw POSTs this first
-            AttachFile._addLogEntry(request, 'ATTDRW', pagename, target + '.tdraw')
+            AttachFile._addLogEntry(request, 'ATTDRW', pagename, target)
             ci.truncate()
             filecontent = filecontent.read() # read file completely into memory
             filecontent = filecontent.replace("\r", "")
@@ -168,7 +168,7 @@
         request = self.request
         pagename = self.pagename
         target = self.target
-        ci = AttachFile.ContainerItem(request, pagename, target + '.tdraw')
+        ci = AttachFile.ContainerItem(request, pagename, target)
         if ci.exists():
             drawurl = ci.member_url('drawing.draw')
             pngurl = ci.member_url('drawing.png')
--- a/MoinMoin/config/multiconfig.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/config/multiconfig.py	Sun Sep 13 16:01:09 2009 +0200
@@ -840,7 +840,6 @@
     ('changed_time_fmt', '%H:%M', "Time format used on Recent``Changes for page edits within the last 24 hours"),
     ('date_fmt', '%Y-%m-%d', "System date format, used mostly in Recent``Changes"),
     ('datetime_fmt', '%Y-%m-%d %H:%M:%S', 'Default format for dates and times (when the user has no preferences or chose the "default" date format)'),
-    ('drawing_action', 'twikidraw', "action for manipulating drawings"),
     ('chart_options', None, "If you have gdchart, use something like chart_options = {'width': 720, 'height': 540}"),
 
     ('edit_bar', ['Edit', 'Comments', 'Discussion', 'Info', 'Subscribe', 'Quicklink', 'Attachments', 'ActionsMenu'],
--- a/MoinMoin/formatter/text_gedit.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/formatter/text_gedit.py	Sun Sep 13 16:01:09 2009 +0200
@@ -95,10 +95,12 @@
     def attachment_drawing(self, url, text, **kw):
         # Todo get it to start the drawing editor on a click
         try:
+            drawing_action = AttachFile.get_action(self.request, url, do='modify')
+            assert drawing_action is not None
             attachment_drawing = wikiutil.importPlugin(self.request.cfg, 'action',
-                                              self.request.cfg.drawing_action, 'gedit_drawing')
+                                              drawing_action, 'gedit_drawing')
             return attachment_drawing(self, url, text, **kw)
-        except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError):
+        except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError, AssertionError):
             return url
 
     def icon(self, type):
--- a/MoinMoin/formatter/text_html.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/formatter/text_html.py	Sun Sep 13 16:01:09 2009 +0200
@@ -655,10 +655,12 @@
     def attachment_drawing(self, url, text, **kw):
         # ToDo try to move this to a better place e.g. __init__
         try:
+            drawing_action = AttachFile.get_action(self.request, url, do='modify')
+            assert drawing_action is not None
             attachment_drawing = wikiutil.importPlugin(self.request.cfg, 'action',
-                                              self.request.cfg.drawing_action, 'attachment_drawing')
+                                              drawing_action, 'attachment_drawing')
             return attachment_drawing(self, url, text, **kw)
-        except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError):
+        except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError, AssertionError):
             return url
 
     # Text ##############################################################
--- a/MoinMoin/parser/text_moin_wiki.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/parser/text_moin_wiki.py	Sun Sep 13 16:01:09 2009 +0200
@@ -765,6 +765,7 @@
                             pagename = self.formatter.page.page_name
                             return m.execute('EmbedObject', u'target=%s' % url)
                 elif scheme == 'drawing':
+                    url = wikiutil.drawing2fname(url)
                     desc = self._transclude_description(desc, url)
                     if desc:
                         tag_attrs= {'alt': desc, 'title': desc, }
@@ -903,6 +904,7 @@
                             self._link_description(desc, target, url) +
                             self.formatter.attachment_link(0))
                 elif scheme == 'drawing':
+                    url = wikiutil.drawing2fname(url)
                     return self.formatter.attachment_drawing(url, desc, alt=desc, **tag_attrs)
             else:
                 if desc:
--- a/MoinMoin/wikiutil.py	Sun Sep 13 02:44:37 2009 +0200
+++ b/MoinMoin/wikiutil.py	Sun Sep 13 16:01:09 2009 +0200
@@ -2228,6 +2228,20 @@
     return basename
 
 
+def drawing2fname(drawing):
+    config.drawing_extensions = ['.tdraw', '.adraw',
+                                 '.svg',
+                                 '.png', '.jpg', '.jpeg', '.gif',
+                                ]
+    fname, ext = os.path.splitext(drawing)
+    # note: do not just check for empty extension or stuff like drawing:foo.bar
+    # will fail, instead of being expanded to foo.bar.tdraw
+    if ext not in config.drawing_extensions:
+        # for backwards compatibility, twikidraw is the default:
+        drawing += '.tdraw'
+    return drawing
+
+
 def mapURL(request, url):
     """
     Map URLs according to 'cfg.url_mappings'.
--- a/docs/CHANGES	Sun Sep 13 02:44:37 2009 +0200
+++ b/docs/CHANGES	Sun Sep 13 16:01:09 2009 +0200
@@ -35,10 +35,15 @@
     * Minimum Xapian requirement is 1.0.6 now.
     * Outdated and unmaintained xapwrap lib was removed.
   * raw action mimetype support: ...?action=raw&mimetype=text/css
-  * new config variable drawing_action for selecting the drawing action
-  * the AttachFile TWikiDraw code refactored to an action.
-  * TextCha feature added to TWikiDraw
-  * AnyWikiDraw applet and source also added a new drawing action anywikidraw
+  * TWikiDraw:
+    * support code was refactored/moved to the twikidraw action.
+    * use drawing:example.tdraw to invoke it (drawing:example also still
+      works for backwards compatibility)
+    * TextCha feature added
+  * AnyWikiDraw:
+    * java applet added, source code see contrib/
+    * support code for it is in anywikidraw action.
+    * use drawing:example.adraw to invoke it
   * SlideShow action and css from moin/extensions for modernized theme added
 
   Bug fixes: