eperez at yaco
Jun 27, 2010, 8:53 AM
Post #1 of 6
DirectoryViewSurrogate as context in FSPageTemplates
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
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)
context = c['context']
for obj in aq_chain(context):
if not IDirectoryView.providedBy(obj):
context = aq_base(context).__of__(obj)
c['context'] = c['here'] = context.__of__(c['container'])
(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
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:
eperez [at] gallin$ ./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
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.
Enrique Pérez Arnaud <eperez [at] yaco>
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