Exemplo n.º 1
0
    def update(self):
        """See interfaces.IWidgets"""

        # Create a unique prefix.
        prefix = util.expandPrefix(self.form.prefix)
        prefix += util.expandPrefix(self.prefix)
        # Walk through each field, making a widget out of it.
        uniqueOrderedKeys = []
        for field in self.form.fields.values():
            # Step 0. Determine whether the context should be ignored.
            #-------------------------------------------------------------------
            if self.draftable:
                ignoreContext = False
            else:
                ignoreContext = self.ignoreContext
                if field.ignoreContext is not None:
                    ignoreContext = field.ignoreContext
            #-------------------------------------------------------------------

            # Step 1: Determine the mode of the widget.
            mode = self.mode
            if field.mode is not None:
                mode = field.mode
            elif field.field.readonly and not self.ignoreReadonly:
                mode = interfaces.DISPLAY_MODE
            elif not ignoreContext:
                # If we do not have enough permissions to write to the
                # attribute, then switch to display mode.
                #try:
                dm = zope.component.getMultiAdapter(
                    (self.content, field.field), interfaces.IDataManager)
                if not dm.canWrite():
                    mode = interfaces.DISPLAY_MODE
                #except TypeError:
                #    # If datamanager can not adapt, then we can't write and
                #    # must ignore context (since it could not adapt)
                #    ignoreContext = True
            # Step 2: Get the widget for the given field.
            shortName = field.__name__
            newWidget = True
            if shortName in self._data:
                # reuse existing widget
                widget = self._data[shortName]
                newWidget = False
            elif field.widgetFactory.get(mode) is not None:
                factory = field.widgetFactory.get(mode)
                widget = factory(field.field, self.request)
            else:
                widget = zope.component.getMultiAdapter(
                    (field.field, self.request), interfaces.IFieldWidget)
            # Step 2.5:  If widget is draftable and no widget exists, create draft
            if self.draftable == False and IDraftable.providedBy(widget):
                proxy = zope.component.queryMultiAdapter((self.content,
                                                        self.request,
                                                        self.form), IZ3cFormDataContext)
                if proxy is not None:
                    proxy.createDraft = True
                    self.content = proxy.adapt()
                    if IZ3cDraft.providedBy(self.content):
                        self.draftable = True
                        ignoreContext = False

            # Step 3: Set the prefix for the widget
            widget.name = prefix + shortName
            widget.id = (prefix + shortName).replace('.', '-')
            # Step 4: Set the context
            widget.context = self.content
            # Step 5: Set the form
            widget.form = self.form
            # Optimization: Set both interfaces here, rather in step 4 and 5:
            # ``alsoProvides`` is quite slow
            zope.interface.alsoProvides(
                widget, interfaces.IContextAware, interfaces.IFormAware)
            # Step 6: Set some variables
            widget.ignoreContext = ignoreContext
            widget.ignoreRequest = self.ignoreRequest
            # Step 7: Set the mode of the widget
            widget.mode = mode
            # Step 8: Update the widget
            widget.update()

            #-------------------------------------------------------------------
            # Save converted widget value on draft if it different from what is
            # already stored on draft
            if self.draftable and self.draftWritable == True and ignoreContext == False:
                dm = zope.component.getMultiAdapter(
                    (self.content, field.field), interfaces.IDataManager)
                try:
                    value = interfaces.IDataConverter(widget).toFieldValue(widget.value)
                    #if getattr(self.content, field.__name__, None) != value:
                    if dm.query() != value:
                        dm.set(value)
                except ValueError:
                    pass
            #-------------------------------------------------------------------

            zope.event.notify(AfterWidgetUpdateEvent(widget))
            # Step 9: Add the widget to the manager
            if widget.required:
                self.hasRequiredFields = True
            uniqueOrderedKeys.append(shortName)
            if newWidget:
                self._data_values.append(widget)
                self._data[shortName] = widget
                zope.location.locate(widget, self, shortName)
            # allways ensure that we add all keys and keep the order given from
            # button items
            self._data_keys = uniqueOrderedKeys
Exemplo n.º 2
0
    def adapt(self):
        """If we are drafting a content item, record form data information to the
        draft, but read existing data from the underlying object.
        """

        # Check to see if we have a cahced copy already
        if IZ3cDraft.providedBy(self.request):
            return self.request.DRAFT.context

        if IDraftable.providedBy(self.request):
            self.createDraft = True

        # Set up the draft (sets cookies, markers, etc)
        draft = getCurrentDraft(self.request, create=False)
        if not draft and not self.createDraft:
            return self.content

        if not draft:
            beginDrafting(self.content, self.form)
            draft = getCurrentDraft(self.request, create=self.createDraft)

        if draft is None:
            return self.content  # return contnet, not context

        context = getattr(draft, 'context', None)

        # Initial draft; populate initial values
        if context is None:
            context = PersistentDict()

            # Get all fields from from, including groups so we can store them
            # on draft
            _fields = []
            for field in self.form.fields.items():
                _fields.append(field)
            if hasattr(self.form, 'groups'):
                for group in self.form.groups:
                    for field in group.fields.items():
                        _fields.append(field)
            for name, field in _fields:
                # Provide default value on draft
                dm = zope.component.getMultiAdapter(
                    (self.content, field.field), interfaces.IDataManager)
                try:
                    value = dm.query(field)
                except TypeError:
                    value = field.field.default or field.field.missing_value

                context[field.field.__name__] = value

            zope.interface.alsoProvides(context, IZ3cDraft)
            zope.interface.alsoProvides(context, IDrafting)
            setattr(draft, 'context', context)

        zope.interface.alsoProvides(draft, IZ3cDraft)
        zope.interface.alsoProvides(self.request, IZ3cDraft)

        # Cache draft
        self.request['DRAFT'] = draft

        return context