Hi

Here in Yaco, while migrating a plone-2.0 site to plone-4.0, we've hit a problem with FSPageTemplates that live within a DirectoryViewSurrogate (within a DirectoryViewSurrgate within a ...) whithin a DirectoryView. The problem is that such a template gets as context the DirectoryViewSurrogate whithin which it lives, and that such an object doesn't get in its aq_inner.aq_parent chain the "real" context object on which the template is called. As a consequence, browser components that get rendered in macros surrounding or within the template get an unexpected context, and bad things happen such as totally wrong breadcrumbs, portlets not getting found by managers, wrong css class for the body element of the produced html, etc.

My investigations, greatly helped by Hanno Schlichting (thanks again, Hanno) on the plone-dev list, have led me to think that the problem lies in the pt_getContext method of Products.CMFCore.FSPageTemplate.FSPageTemplate. This method is directly got from Products.PageTemplates.ZopePageTemplate.ZopePageTemplate. IMHO, that method makes sense in a PageTemplate living in the zodb, but not in nested directories in the filesystem. So my proposed solution goes through giving a special pt_getContext method to FSPageTemplate. The requirements of that method would be:

* Provide a context that is the innermost DirectoryViewSurrogate, with an aq_inner.aq_parent chain that directly passes from it to the "real" context object on which the template is called. This way, "navigational" elements such as the breadcrumbs get a proper path.

* Provide the intermediate DirectoryViewSurrogates in the aq_chain of the final context. This way, if the FSPageTemplate relies by acquisition on scripts or zsql methods or thigs like that that live in those intermediate DVS, it will find them.

* Apply a similar logic to the container variable in the template? not so sure about this, my stuff works with and without the c['container'] modification, so I have commented it out in the method below.

with this, I have come up with the following method for Products.CMFCore.FSPageTemplate.FSPageTemplate:



from Products.CMFCore.interfaces import IDirectoryView
from Acquisition import aq_inner, aq_chain, aq_parent, aq_base

...

    zpt_pt_getContext = ZopePageTemplate.pt_getContext.im_func

    def pt_getContext(self, *args, **kwargs):
        c = self.zpt_pt_getContext(*args, **kwargs)
        if IDirectoryView.providedBy(c['context']):
            context = c['context']
            for obj in aq_chain(context):
                if not IDirectoryView.providedBy(obj):
                    context = aq_base(context).__of__(obj)
                    break
#c['container'] = c['container'].__of__(aq_parent(aq_inner(context)))
            c['context'] = c['here'] = context.__of__(c['container'])
        return c

(In my thunderbird getting the list from gmane the formatting gets right, but just in case, I attach a diff file).

I have run the CMFCore tests on a https://svn.plone.org/svn/plone/buildouts/plone-coredev/branches/3.3 buildout (not sure if it's the right place to run them) and they give the same results with and without the patch, and commenting out or not the container modification in the patch:


epe...@gallina$ ./bin/instance test -s Products.CMFCore
...
Error in test test_copy_cant_create_target_metatype_not_supported
...
Error in test test_move_cant_create_target_metatype_not_allowed
...
Error in test test_move_cant_create_target_metatype_not_supported
...
Total: 610 tests, 0 failures, 3 errors

So, questions:

Does this sound right? Is someone else encountering similar problems? If the answer to the previous questions are yes and (yes or not), what should be my next step?

Thanks for getting this far in this rather longish post.

Best regards,

--
Enrique Pérez Arnaud <epe...@yaco.es>
Yaco Sistemas SL| http://www.yaco.es
C/ Rioja 5, 41001 Sevilla (España)
Tel: (+34) 954 50 00 57
Fax 954 50 09 29
--- FSPageTemplate.py.orig	2010-06-27 17:39:56.000000000 +0200
+++ FSPageTemplate.py	2010-06-27 17:40:21.000000000 +0200
@@ -18,6 +18,7 @@
 import re
 
 import Globals
+from Acquisition import aq_inner, aq_chain, aq_parent, aq_base
 from AccessControl import ClassSecurityInfo
 from AccessControl import getSecurityManager
 from OFS.Cache import Cacheable
@@ -25,6 +26,7 @@
 from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate, Src
 from Shared.DC.Scripts.Script import Script
 
+from Products.CMFCore.interfaces import IDirectoryView
 from DirectoryView import registerFileExtension
 from DirectoryView import registerMetaType
 from FSObject import FSObject
@@ -238,7 +240,19 @@
     document_src = ZopePageTemplate.document_src.im_func
 
     pt_getContext = ZopePageTemplate.pt_getContext.im_func
-    pt_getContext = ZopePageTemplate.pt_getContext.im_func
+    zpt_pt_getContext = ZopePageTemplate.pt_getContext.im_func
+
+    def pt_getContext(self, *args, **kwargs):
+        c = self.zpt_pt_getContext(*args, **kwargs)
+        if IDirectoryView.providedBy(c['context']):
+            context = c['context']
+            for obj in aq_chain(context):
+                if not IDirectoryView.providedBy(obj):
+                    context = aq_base(context).__of__(obj)
+                    break
+            #c['container'] = c['container'].__of__(aq_parent(aq_inner(context)))
+            c['context'] = c['here'] = context.__of__(c['container'])
+        return c
 
     ZScriptHTML_tryParams = ZopePageTemplate.ZScriptHTML_tryParams.im_func
 
_______________________________________________
Zope-CMF maillist  -  Zope-CMF@zope.org
https://mail.zope.org/mailman/listinfo/zope-cmf

See https://bugs.launchpad.net/zope-cmf/ for bug reports and feature requests

Reply via email to