from five import grok
import z3c.form
import plone.z3cform
from plone.z3cform.fieldsets.extensible import ExtensibleForm
from Acquisition import aq_inner
from plone.z3cform.interfaces import IFormWrapper
from plone.z3cform.fieldsets.interfaces import IFormExtender
from z3c.form import subform
from z3c.form.form import EditForm
from z3c.form.interfaces import IFormLayer, ISubForm, IWidgets
from zope.interface import alsoProvides, noLongerProvides
from zope.interface.interfaces import IInterface
from zope.publisher.interfaces.browser import IBrowserApplicationRequest
import zope
import Products
def addLayer(request, layer):
alsoProvides(request, layer)
def fix_z2_request(request):
"""
Inspired by plone.z3cform.z2, without the IBrowserApplicationRequest filter.
request must be patched for forms to be rendered in Zope2
maybe we had IBrowserApplicationRequest, so we need to fix the request.
"""
if not plone.z3cform.z2.IFixedUpRequest.providedBy(request):
# try to fix locale, it can fail with attribute error weither which kind of request it is
request._locale = plone.z3cform.z2.setup_locale(request)
try:
request.locale = request._locale
except:
pass
plone.z3cform.z2.add_getURL(request)
plone.z3cform.z2.decode.processInputs(request)
addLayer(request, plone.z3cform.z2.IFixedUpRequest)
def fix_z2_obj_request(self):
"""Wrapper for object containing a request."""
fix_z2_request(self.request)
class FormWrapper(grok.View):
"""
Base wrapper to z3c.form, just register a class which set the form attribute.
You have a classical grok.View instance with an attribute ``form_instance``
which is the wrapped z3c.form.form.Form instance.
>>> class Klass(FormWrapper):
... context = grok.context(someinterface)
... form = FormKlass
You can also override the layer attribute.
"""
grok.baseclass()
grok.context(zope.interface.Interface)
grok.implements(IFormWrapper)
form = None # z3c.form class
index = None # template
view_request_layer = None # wrapper view layer
form_request_layer = None # form instance layer
def __init__(self, *args, **kwargs):
grok.View.__init__(self, *args, **kwargs)
if self.view_request_layer: self.addLayer(self.view_request_layer)
fix_z2_obj_request(self)
self.switch_on_form_layer()
self.form_instance = self.form(aq_inner(self.context), self.request)
self.form_instance.__name__ = self.__name__
if getattr(self, 'template', None):
self.index = self.template
def switch_on_form_layer(self, layer=None):
"""
we need that to render forms in zope2 !
"""
if not layer:
layer = IFormLayer
if self.form_request_layer:
layer = self.form_request_layer
# check that the layer is interface:
if IInterface.providedBy(layer):
if not layer.providedBy(self.request):
self.addLayer(layer)
def addLayer(self, layer):
alsoProvides(self.request, layer)
def update(self, *args, **kwargs):
self.compute_widgets()
grok.View.update(self, *args, **kwargs)
def compute_widgets(self):
"""
shortcut 'widget' dictionary for all fieldsets
stolen from plone.autoform_instance/plone/autoform_instance/view.py
"""
self.form_instance.update()
self.form_instance.w = {}
for k, v in self.form_instance.widgets.items():
self.form_instance.w[k] = v
groups = []
self.form_instance.fieldsets = {}
if getattr(self.form_instance, 'groups', None):
for idx, group in enumerate(self.form_instance.groups):
#group = groupFactory(self.form_instance.context,
# self.form_instance.request,
# self.form_instance)
group.update()
for k, v in group.widgets.items():
self.form_instance.w[k] = v
groups.append(group)
group_name = getattr(group, '__name__', str(idx))
self.form_instance.fieldsets[group_name] = group
self.form_instance.groups = tuple(groups)
def render_form(self):
"""
call this method in templates to have the full html rendered form
"""
return self.form_instance.render()
# stolen from plone.directives.form.form.DisplayForm
def render(self, *args, **kwargs):
template = getattr(self, 'template', None)
if template is not None:
return self.template.render()
return zope.publisher.publish.mapply(self.render, (), self.request)
render.base_method = True
class PloneFormWrapper(FormWrapper):
"""
Use that nice plone with fieldsets and kss template
explicitly rather than the basic z3c.form template
"""
grok.baseclass()
view_request_layer = Products.CMFDefault.interfaces.ICMFDefaultSkin
class ContextLessForm(z3c.form.form.BaseForm):
grok.baseclass()
ignoreContext = True
def updateWidgets(self):
self.updateFields()
for action in self.parentForm.actions.executedActions:
adapter = zope.component.queryMultiAdapter(
(self, self.request, self.getContent(), action),
interface=interfaces.IActionHandler)
if adapter:
adapter()
class PloneForm(ExtensibleForm, z3c.form.form.Form):
grok.baseclass()
def update(self):
ExtensibleForm.update(self)
# already in z3c.form.group.Group.update
#z3c.form.form.Form.update(self)
def updateWidgets(self):
return z3c.form.form.Form.updateWidgets(self)
class PloneEditForm(EditForm, PloneForm):
grok.baseclass()
def __init__(self, context, request):
PloneForm.__init__(self, context, request)
return EditForm.__init__(self, context, request)
class PloneEditContextLessForm(PloneEditForm, ContextLessForm):
grok.baseclass()
def update(self):
ContextLessForm.update(self)
return PloneEditForm.update(self)
class PloneSubForm(PloneForm):
grok.baseclass()
grok.implements([z3c.form.interfaces.ISubForm, z3c.form.interfaces.IHandlerForm]
+list(zope.interface.providedBy(PloneForm)))
def __init__(self, context, request, parentf):
PloneForm.__init__(self, context, request)
self.parentForm = self.__parent__ = parentf
self.ignoreContext = self.parentForm.ignoreContext