diff --git a/wiki/README.txt b/wiki/README.txt
index db0ecdd..bab221e 100644
--- a/wiki/README.txt
+++ b/wiki/README.txt
@@ -82,4 +82,43 @@ Links to not yet existing pages
?More...
+ >>> len(links)
+ 2
+External links
+--------------
+
+ >>> linksPage = wiki.createPage('links')
+ >>> linksPage.text = '''
+ ... **A collection of interesting links**
+ ...
+ ... - http://python.org
+ ... - `Zope `_
+ ... '''
+
+An absolute URL given as link target will not be changed in the process.
+
+ >>> print linksPage.render(TestRequest())
+ A collection of interesting links
+
+
+Nevertheless the links are registered in the link manager.
+
+ >>> len(links)
+ 4
+
+When we render external links repeatedly no new link objects will be
+created.
+
+ >>> print linksPage.render(TestRequest())
+ A collection of interesting links
+
+
+ >>> len(links)
+ 4
diff --git a/wiki/base/link.py b/wiki/base/link.py
index 884c00f..754f026 100644
--- a/wiki/base/link.py
+++ b/wiki/base/link.py
@@ -17,7 +17,7 @@
#
"""
-Basic (sample) implementations for links and link management
+Basic (sample) implementations for links and link management.
$Id$
"""
@@ -111,16 +111,18 @@ class LinkProcessor(object):
def process(self):
wiki = self.source.getWiki()
manager = wiki.getManager()
- sourceUid = self.source.getUid()
+ sourceUid = self.source.uid
lmName = self.source.getConfig('linkManager')
- lm = wiki.getManager().getPlugin(ILinkManager, lmName)
+ lm = manager.getPlugin(ILinkManager, lmName)
existing = lm.query(source=sourceUid, name=self.targetName)
if existing:
- link = list(existing)[0]
+ link = existing.next()
+ #print '*** #1', self.targetName, link
target = manager.getObject(link.target)
else:
target = wiki.getPage(self.targetName)
- targetUid = target is not None and target.getUid() or None
+ #print '*** #2', self.targetName, target
+ targetUid = target is not None and target.uid or None
link = lm.createLink(self.targetName, sourceUid, targetUid)
if link.refuri is None:
if self.request is not None:
@@ -128,15 +130,12 @@ class LinkProcessor(object):
link.refuri = '%s/create.html?linkid=%s' % (
absoluteURL(wiki, self.request), link.identifier)
else:
- link.refuri = self.getTargetURI(target)
+ link.refuri = target.getURI(self.request)
self.setURI(link.refuri)
if target is None:
self.markPresentation('create')
self.addText('?')
- def getTargetURI(self, obj):
- return absoluteURL(obj, self.request)
-
def setURI(self, uri):
raise ValueError('To be implemented by subclass.')
@@ -145,3 +144,4 @@ class LinkProcessor(object):
def addText(self, text):
raise ValueError('To be implemented by subclass.')
+
diff --git a/wiki/base/wiki.py b/wiki/base/wiki.py
index e83dc4e..181dfe0 100644
--- a/wiki/base/wiki.py
+++ b/wiki/base/wiki.py
@@ -22,10 +22,12 @@ A Wiki manager managing wikis and wiki-related objects, esp plugins.
$Id$
"""
+from zope.app.intid.interfaces import IIntIds
from zope import component
from zope.interface import implements
-from zope.app.intid.interfaces import IIntIds
+from zope.traversing.browser import absoluteURL
+from cybertools.wiki.common import protocols, ExternalPage
from cybertools.wiki.interfaces import IWikiConfiguration
from cybertools.wiki.interfaces import IWikiManager, IWiki, IWikiPage
from cybertools.wiki.interfaces import IParser, IWriter
@@ -62,9 +64,17 @@ class WikiManager(BaseConfiguration):
return component.getUtility(IIntIds).getId(obj)
def getObject(self, uid):
- if uid is None:
- return None
- return component.getUtility(IIntIds).getObject(int(uid))
+ obj = self.resolveUid(uid)
+ if obj is None:
+ return component.getUtility(IIntIds).getObject(int(uid))
+ return obj
+
+ def resolveUid(self, uid):
+ if isinstance(uid, basestring) and ':' in uid:
+ protocol, address = uid.split(':', 1)
+ if protocol.lower() in protocols:
+ return ExternalPage(uid)
+ return None
# configuration
@@ -103,6 +113,10 @@ class Wiki(BaseConfiguration):
del self.pages[name]
def getPage(self, name):
+ if ':' in name:
+ protocol, address = name.split(':', 1)
+ if protocol in protocols:
+ return ExternalPage(name)
return self.pages.get(name)
def listPages(self):
@@ -151,9 +165,15 @@ class WikiPage(BaseConfiguration):
def postprocess(self, result):
return result
- def getUid(self):
+ # IWebResource
+
+ @property
+ def uid(self):
return self.getWiki().getManager().getUid(self)
+ def getURI(self, request):
+ return absoluteURL(self, request)
+
# configuration
def getConfigParent(self):
diff --git a/wiki/common.py b/wiki/common.py
new file mode 100644
index 0000000..8c149fd
--- /dev/null
+++ b/wiki/common.py
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+
+"""
+Common basic generic stuff.
+
+$Id$
+"""
+
+from zope.interface import implements
+
+from cybertools.wiki.interfaces import IWebResource
+
+
+protocols = set(['dav', 'file', 'ftp', 'http', 'https', 'javascript',
+ 'mailto', 'sftp', 'smb'])
+
+
+class ExternalPage(object):
+
+ implements(IWebResource)
+
+ def __init__(self, uid):
+ self.uid = uid
+
+ def getURI(self, request):
+ return self.uid
+
diff --git a/wiki/interfaces.py b/wiki/interfaces.py
index d7b8492..d50648f 100644
--- a/wiki/interfaces.py
+++ b/wiki/interfaces.py
@@ -105,7 +105,20 @@ class IWiki(Interface):
"""
-class IWikiPage(Interface):
+class IWebResource(Interface):
+ """ An object (may be a proxy or some other kind of representation) that
+ may be addressed by a Unique (Resource) Identifier (UID or URI).
+ """
+
+ uid = Attribute('A string uniquely addressing the object within a '
+ 'certain context (local pages) or globally.')
+
+ def getURI(self, request):
+ """ Return a unique resource identifier based on the request given.
+ """
+
+
+class IWikiPage(IWebResource):
""" An object representing a page of a wiki.
"""
@@ -230,6 +243,8 @@ class ILink(Interface):
'for external links - the target URI.')
targetFragment = Attribute('Optional: an address part leading to a '
'text anchor or the part of an image.')
+ targetParameters = Attribute('Optional: a dictionary of URI parameters '
+ 'that will have to be appended to the link to the target object.')
refuri = Attribute('The URI linking to the target object.')
user = Attribute('Optional: a string denoting the creator of the record.')
run = Attribute('Optional: May be used to group the links from a certain '