Ensure context is a content item of some sort.

This commit is contained in:
Laurence Rowe 2012-09-27 19:57:44 +01:00
parent 7f6e993c75
commit 1a10c0e309
4 changed files with 61 additions and 44 deletions

View File

@ -4,6 +4,9 @@ Changelog
1.0.6 (unreleased)
------------------
* Ensure context is a content item of some sort.
[elro]
* Import getSite from zope.component to avoid dependency on zope.app.component.
[hvelarde]

View File

@ -1,6 +1,5 @@
import logging
from Acquisition.interfaces import IAcquirer
import Missing
from zope.interface import implements
from zope.component import getMultiAdapter
@ -8,15 +7,8 @@ from zope.component import getMultiAdapter
from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleTerm
from zope.app.component.hooks import getSite
try:
from zope.globalrequest import getRequest
getRequest # pyflakes
except ImportError:
# Fake it
getRequest = object
from plone.app.layout.navigation.interfaces import INavigationQueryBuilder
from plone.app.layout.navigation.root import getNavigationRootObject
from plone.app.vocabularies.catalog import parse_query
from Products.CMFCore.utils import getToolByName
@ -24,6 +16,7 @@ from Products.ZCTextIndex.ParseTree import ParseError
from plone.formwidget.contenttree.interfaces import IContentSource
from plone.formwidget.contenttree.interfaces import IContentFilter
from plone.formwidget.contenttree.utils import closest_content
from OFS.interfaces import ITraversable
@ -73,8 +66,8 @@ class PathSource(object):
def __init__(self, context, selectable_filter, navigation_tree_query=None):
self.context = context
query_builder = getMultiAdapter((context, self),
nav_root = getNavigationRootObject(context, None)
query_builder = getMultiAdapter((nav_root, self),
INavigationQueryBuilder)
query = query_builder()
@ -239,7 +232,7 @@ class PathSourceBinder(object):
def __call__(self, context):
return self.path_source(
self._find_page_context(context),
closest_content(context),
selectable_filter=self.selectable_filter,
navigation_tree_query=self.navigation_tree_query)
@ -248,28 +241,6 @@ class PathSourceBinder(object):
# now and pass through to the bound version
return self(None).__contains__(value)
def _find_page_context(self, given_context=None):
"""Try to find a usable context, with increasing agression"""
# Normally, we should be given a useful context (e.g the page)
c = given_context
if IAcquirer.providedBy(c):
return c
# Subforms (e.g. DataGridField) may not have a context set, find out
# what page is being published
c = getattr(getRequest(), 'PUBLISHED', None)
if IAcquirer.providedBy(c):
return c
# During widget traversal nothing is being published yet, use getSite()
c = getSite()
if IAcquirer.providedBy(c):
return c
# During kss_z3cform_inline_validation, PUBLISHED and getSite() return
# a Z3CFormValidation object. What we want is it's context.
c = getattr(getattr(getRequest(), 'PUBLISHED', None), 'context', None)
if IAcquirer.providedBy(c):
return c
raise ValueError('Cannot find suitable context to bind to source')
class ObjPathSourceBinder(PathSourceBinder):
path_source = ObjPathSource

View File

@ -0,0 +1,48 @@
from Acquisition import aq_base
from Products.CMFCore.interfaces import IContentish
from Products.CMFCore.interfaces import IFolderish
from zope.component.hooks import getSite
try:
from zope.globalrequest import getRequest
getRequest # pyflakes
except ImportError:
# Fake it
getRequest = object
def closest_content(context=None):
"""Try to find a usable context, with increasing agression"""
# Normally, we should be given a useful context (e.g the page)
c = context
c = _valid_context(c)
if c is not None:
return c
# Subforms (e.g. DataGridField) may not have a context set, find out
# what page is being published
c = getattr(getRequest(), 'PUBLISHED', None)
c = _valid_context(c)
if c is not None:
return c
# During widget traversal nothing is being published yet, use getSite()
c = getSite()
c = _valid_context(c)
if c is not None:
return c
raise ValueError('Cannot find suitable context to bind to source')
def _valid_context(context):
"""Walk up until finding a content item."""
# Avoid loops
seen = set()
while context is not None and aq_base(context) not in seen:
seen.add(aq_base(context))
if (IContentish.providedBy(context)
or IFolderish.providedBy(context)):
return context
parent = getattr(context, '__parent__', None)
if parent is None:
parent = getattr(context, 'context', None)
context = parent
return None

View File

@ -11,8 +11,6 @@ import z3c.form.interfaces
import z3c.form.widget
import z3c.form.util
from zope.component.hooks import getSite
from plone.app.layout.navigation.interfaces import INavtreeStrategy
from plone.app.layout.navigation.navtree import buildFolderTree
@ -24,6 +22,7 @@ from Products.Five.browser import BrowserView
from plone.formwidget.contenttree.interfaces import IContentTreeWidget
from plone.formwidget.contenttree import MessageFactory as _
from plone.formwidget.contenttree.utils import closest_content
class Fetch(BrowserView):
@ -80,14 +79,13 @@ class Fetch(BrowserView):
level = self.request.form.get('rel', 0)
navtree_query = source.navigation_tree_query.copy()
navtree_query['path'] = {'depth': 1, 'query': directory}
if directory is not None:
navtree_query['path'] = {'depth': 1, 'query': directory}
if 'is_default_page' not in navtree_query:
navtree_query['is_default_page'] = False
content = context
if not IAcquirer.providedBy(content):
content = getSite()
content = closest_content(context)
strategy = getMultiAdapter((content, widget), INavtreeStrategy)
catalog = getToolByName(content, 'portal_catalog')
@ -138,10 +136,7 @@ class ContentTreeBase(Explicit):
return self.bound_source.getTermByBrain(brain)
def render_tree(self):
content = self.context
if not IAcquirer.providedBy(content):
content = getSite()
content = closest_content(self.context)
source = self.bound_source
strategy = getMultiAdapter((content, self), INavtreeStrategy)