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: