Virtual Pages
A virtual page is a wiki page which gets its content from a script instead of reading it from a file
diff <Page.py from MoinMoin 1.3.2> <Page.py with virtual pages>
--- /home/nick/moin-1.3.2/MoinMoin/Page.py 2005-01-22 08:37:23.000000000 -0600
+++ Page.py 2005-02-18 15:57:10.000000000 -0600
@@ -65,6 +65,14 @@
self.reset()
+ if self.__class__ == Page:
+ result = virtualPageLookup(request, self.page_name)
+ if result:
+ self.__class__ = VirtualPage
+ self.generator = result[0]
+ self.match_object = result[1]
+ self.data = None
+
def reset(self):
""" Reset page state """
page_name = self.page_name
@@ -1575,3 +1583,127 @@
return text
+class VirtualPage(Page):
+ def get_current_from_pagedir(self, pagedir):
+ return 0
+
+ def get_rev_dir(self, pagedir, rev=0):
+ if rev == 0:
+ exists = True
+ else:
+ exists = False
+ return "", rev, exists
+
+ def get_rev(self, use_underlay=-1, rev=0):
+ if rev == 0:
+ exists = True
+ else:
+ exists = False
+
+ return "", rev, exists
+
+ def current_rev(self):
+ return 0
+
+ def get_real_rev(self):
+ return 0
+
+ def getPageBasePath(self, use_underlay):
+ return ""
+
+ def getPageStatus(self, *args, **kw):
+ return "",""
+
+ def getPagePath(self, *args, **kw):
+ return ""
+
+ def _text_filename(self, **kw):
+ return ""
+
+ def _tmp_filename(self):
+ return ""
+
+ def _last_edited(self, request):
+ return None
+
+ def last_edit(self, request):
+ return {'timestamp' : 0, 'editor' : '?'}
+
+ def lastEditInfo(self, request=None):
+ return {'editor' : None, 'time' : 0}
+
+ def isUnderlayPage(self, includeDeleted=True):
+ return False
+
+ def isStandardPage(self, includeDeleted=True):
+ return False
+
+ def exists(self, rev=0, domain=None, includeDeleted=False):
+ return True
+
+ def size(self):
+ if not self.data:
+ self.get_raw_body()
+ return len(self.data)
+
+ def mtime_usecs(self):
+ return 0
+
+ def mtime_printable(self):
+ return "Beginning of time"
+
+ def getPageList(self, user=None, rootpagename=None):
+ return []
+
+ def getPageDict(self, user=None, rootpagename=None):
+ return {}
+
+ def get_raw_body(self):
+ if not self.data:
+ self.data = self.generator(self.page_name, self.match_object)
+ return self.data
+
+ def set_raw_body(self, body, modified=0):
+ self.data = body
+
+ def getSubscribers(self, request, **kw):
+ return []
+
+ def getRevList(self):
+ return [0]
+
+ def olderrevision(self, rev=0):
+ return 0
+
+ def isWritable(self):
+ return False
+
+
+
+
+
+virtual_pages = []
+
+def findVirtualPagePlugins(cfg):
+ from wikiutil import getPlugins, importPlugin
+ plugins = getPlugins("virtual", cfg)
+
+ for vp in plugins:
+ regex = importPlugin(cfg, "virtual", vp, function="regex")
+ filter = importPlugin(cfg, "virtual", vp, function="filter")
+ generator = importPlugin(cfg, "virtual", vp)
+ if regex != None and filter != None and generator != None:
+ virtual_pages.append((re.compile(regex), filter, generator))
+
+def virtualPageLookup(request, page_name):
+ if virtual_pages == []:
+ findVirtualPagePlugins(request.cfg)
+
+ for (regex, filter, generator) in virtual_pages:
+ mo = regex.match(page_name)
+ if mo:
+ if filter(page_name, mo):
+ return (generator, mo)
+
+ return None
+I guess that not all functions of VirtualPage are needed. Furthermore I'm not sure if all of them are defined correctly.
To have virtual pages you need a directory plugin/virtual. A plugin in this directory must have three things
- a string called regex
- a function called filter
- a function called execute
The page's name is matched against the regex. If it matches the plugin is considered to be responsible for this page. So regex defines a namespace for wiki pages. To be able to exclude specific pages from this namespace without having to define a complex regex, the function filter is called if the regex matches. The function filter gets the pagename and returns a bool. If filter returns false the next virtual page plugin is checked for responsibility. If none matches the page is considered to be a normal wiki page. As soon as the VirtualPage is supposed to read its contents from the disk the execute fuction is called instead.
-- AlexanderBernauer alex at copton net
- Page.py is unchanged from 1.3.2 to 1.3.3, so this patch works on that fine too.
Couple of other things that are important to know: In your plugins/virtual directory, you need an __init__.py with a couple lines of code -- just steal the __init__.py from the macros or actions directories. Your execute function needs to take two arguments: the page's name, and a regex match object (I believe this is the result of matching your regex string). execute should return a string with the contents of the page. Also, this patch doesn't pass the request to your execute(), which kind of sucks. A quick fix is to change this line in Page.py:
self.data = self.generator(self.page_name, self.match_object)
to:
self.data = self.generator(self.request, self, self.match_object)
And make your execute function now take the arguments: (request, page, match). You can still access page_name through page.page_name. Another issue: although virtual pages are immutable and don't have an edit link, you can still tack on ?action=edit to the URL and be allowed to edit them (it'll just save it as a normal page). Basically VirtualPage and PageEditor are ignorant of each other and PageEditor doesn't know when a page is a virtual page, so it still lets you edit/rename/delete them. -- NickWelch
See also:
