Permalink
Browse files

Initial support for mapping child sites to different URLs. To use:

* Add the following to your ZCML:
  <includeOverrides package="collective.lineage" file="overrides.zcml" />
* Provide a registry.xml value for collective.lineage.interfaces.ILineageSettings.vhm_map
  * Keys will be path to the child site(s) and the value is the URL to
    be used to access that child site
    NOTE: only the netloc portion of the URL is used
  • Loading branch information...
1 parent 259768e commit e443dca3680ac03d54295b03391d748c6f49009a @davidblewett davidblewett committed Aug 29, 2012
View
@@ -4,4 +4,4 @@ Things that need to be done before next release
- Write tests for p4a.subtyper code and merge branch down into trunk, then release
- Finish up subscribers for site deletion
- Large Folder child site? normal AT folder? plone.app.content container?
-
+- Investigate inability to override the absolute_url for the lineage container itself
@@ -0,0 +1,59 @@
+import urlparse
+
+from zope.component import getUtility
+
+from OFS.absoluteurl import AbsoluteURL
+
+from plone.registry.interfaces import IRegistry
+
+from collective.lineage.interfaces import ILineageSettings
+
+
+class LineageAbsoluteURL(AbsoluteURL):
+ """An absolute_url adapter for generic objects in Zope 2 that
+ checks if the context is inside an IChildSite with a customized
+ URL.
+ """
+ def __str__(self):
+ mapped_url = map_url('/'.join(self.context.getPhysicalPath()),
+ self.request)
+ if mapped_url is None:
+ return super(LineageAbsoluteURL, self).__str__()
+ else:
+ return mapped_url
+
+
+def map_url(path, request):
+ """Given a path in the site, apply any URL transforms
+ stored in the registry. Returns None if no map exists for the given path.
+ """
+ # Be careful to not try to retrieve the object
+ registry = getUtility(IRegistry)
+ settings = registry.forInterface(ILineageSettings)
+ vhm_map = getattr(settings, 'vhm_map', {})
+ child_site_url = ''
+ scheme = urlparse.urlparse(request.getURL())[0]
+
+ # We want to sort by descending path distance,
+ # so that deeper child sites don't get incorrectly swallowed
+ # by parent child sites
+ roots = sorted(vhm_map.keys(), key=lambda x: -len(x.split('/')))
+ for site_mgr_root in roots:
+ child_site_netloc = urlparse.urlparse(vhm_map[site_mgr_root])[1]
+ if path.startswith(site_mgr_root):
+ break
+
+ if not child_site_netloc or not site_mgr_root:
+ # Didn't find any defined maps for this path
+ return None
+
+ my_relative_path = path.partition(site_mgr_root)[-1]
+
+ url = urlparse.urlunsplit([
+ scheme,
+ child_site_netloc,
+ my_relative_path,
+ '',
+ ''
+ ])
+ return url
@@ -0,0 +1,13 @@
+from Acquisition import aq_parent
+
+from collective.lineage.absoluteurl import map_url
+
+
+def getURL(self, relative=0):
+ parent = aq_parent(self)
+ mapped_url = map_url(self.getPath(), parent.REQUEST)
+ if mapped_url is None:
+ # Didn't find any defined maps for this brain
+ return self._getURL()
+ else:
+ return mapped_url
@@ -11,7 +11,9 @@ class LineageSettingsEditForm(controlpanel.RegistryEditForm):
def updateFields(self):
super(LineageSettingsEditForm, self).updateFields()
-
+ # There isn't a widget to nicely edit a Dict schema field yet
+ # see: https://dev.plone.org/ticket/11932
+ self.fields = self.fields.omit('vhm_map')
def updateWidgets(self):
super(LineageSettingsEditForm, self).updateWidgets()
@@ -43,3 +43,11 @@ class ILineageSettings(Interface):
under the 'Sub-types' tab. Default is 'Child Site'"),
required=False,
default=u'',)
+
+ vhm_map = schema.Dict(title=_(u"VHM Path Map"),
+ description=_(u"help_vhm_map",
+ default=u"You can define a mapping of paths in \
+ the site hierachy and the hostname \
+ used to access that part of the tree."),
+ required=False,
+ default={},)
@@ -0,0 +1,53 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:browser="http://namespaces.zope.org/browser"
+ xmlns:zcml="http://namespaces.zope.org/zcml"
+ i18n_domain="collective.lineage">
+
+ <configure
+ zcml:condition="installed collective.lineage">
+
+ <subscriber
+ for="zope.processlifetime.IDatabaseOpenedWithRoot"
+ handler=".subscribers.addBrainOverride"
+ />
+
+ <browser:page
+ for="Products.Archetypes.interfaces.IBaseContent"
+ name="absolute_url"
+ class=".absoluteurl.LineageAbsoluteURL"
+ permission="zope.Public"
+ allowed_interface="zope.traversing.browser.interfaces.IAbsoluteURL"
+ />
+
+ <view
+ for="Products.Archetypes.interfaces.IBaseContent"
+ factory=".absoluteurl.LineageAbsoluteURL"
+ type="zope.publisher.interfaces.http.IHTTPRequest"
+ permission="zope.Public"
+ provides="zope.traversing.browser.interfaces.IAbsoluteURL"
+ />
+
+ <configure
+ zcml:condition="installed plone.dexterity">
+
+ <browser:page
+ for="plone.dexterity.interfaces.IDexterityContent"
+ name="absolute_url"
+ class=".absoluteurl.LineageAbsoluteURL"
+ permission="zope.Public"
+ allowed_interface="zope.traversing.browser.interfaces.IAbsoluteURL"
+ />
+
+ <view
+ for="plone.dexterity.interfaces.IDexterityContent"
+ factory=".absoluteurl.LineageAbsoluteURL"
+ type="zope.publisher.interfaces.http.IHTTPRequest"
+ permission="zope.Public"
+ provides="zope.traversing.browser.interfaces.IAbsoluteURL"
+ />
+
+ </configure>
+
+ </configure>
+
+</configure>
@@ -60,3 +60,23 @@ def disableChildSite(event):
if event.subtype is not None:
folder = event.object
disableFolder(folder)
+
+def addBrainOverride(event):
+ """When Plone starts up, add our override of AbstractCatalogBrain.getURL
+ """
+ # Ideally, we could use `useBrains`,
+ # But ZCatalog forces AbstractCatalogBrain first in the MRO.
+ from Products.ZCatalog.CatalogBrains import AbstractCatalogBrain
+ from collective.lineage import brains
+ AbstractCatalogBrain._getURL = AbstractCatalogBrain.getURL
+ AbstractCatalogBrain.getURL = brains.getURL
+
+ #from zope.app.appsetup.bootstrap import getInformationFromEvent
+ #from Products.CMFPlone.interfaces.siteroot import IPloneSiteRoot
+ #from collective.lineage.brains import VHMAwareBrain
+ #db, connection, root, root_folder = getInformationFromEvent(event)
+
+ #for obj_id, obj in root_folder.items():
+ # if IPloneSiteRoot.providedBy(obj):
+ # catalog = getToolByName(obj, 'portal_catalog')
+ # catalog._catalog.useBrains(VHMAwareBrain)

0 comments on commit e443dca

Please sign in to comment.