From 63fe33396613c25234436d9708f469fd88eba04e Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Sun, 16 May 2021 09:51:41 +0300 Subject: [PATCH 01/12] WIP on making services work on plone root --- .gitignore | 1 + .../restapi/services/form_data/configure.zcml | 10 ++++++++++ .../restapi/services/submit_form/configure.zcml | 10 ++++++++++ .../formsupport/restapi/services/submit_form/post.py | 12 +++++++----- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 29bcf677..f07b979c 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ report.html .tox/ reports/ # excludes +*~ diff --git a/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml b/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml index 1ec1ea1a..016aaf8c 100644 --- a/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml +++ b/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml @@ -11,6 +11,16 @@ permission="cmf.ModifyPortalContent" layer="collective.volto.formsupport.interfaces.ICollectiveVoltoFormsupportLayer" /> + + + + + + diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index 7b30d5c7..f19fd71f 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +from collective.volto.formsupport import _ +from collective.volto.formsupport.interfaces import IFormDataStore from email.message import EmailMessage from plone import api from plone.protect.interfaces import IDisableCSRFProtection @@ -7,12 +9,9 @@ from plone.restapi.services import Service from Products.CMFPlone.interfaces.controlpanel import IMailSchema from zExceptions import BadRequest -from zope.component import getMultiAdapter -from zope.component import getUtility -from zope.interface import alsoProvides -from collective.volto.formsupport import _ +from zope.component import getMultiAdapter, getUtility from zope.i18n import translate -from collective.volto.formsupport.interfaces import IFormDataStore +from zope.interface import alsoProvides import codecs import six @@ -29,6 +28,9 @@ def __init__(self, context, request): self.block = self.get_block_data(block_id=self.block_id) def reply(self): + import pdb + + pdb.set_trace() self.validate_form() store_action = self.block.get("store", False) From 8ce89742743c2e15b0699249ef7af44ad0f7a40a Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Sun, 16 May 2021 20:05:54 +0300 Subject: [PATCH 02/12] Remove pdb --- .../volto/formsupport/restapi/services/submit_form/post.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index f19fd71f..5769bb73 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -28,9 +28,6 @@ def __init__(self, context, request): self.block = self.get_block_data(block_id=self.block_id) def reply(self): - import pdb - - pdb.set_trace() self.validate_form() store_action = self.block.get("store", False) From fa2c31cc017582b0c9a9b62be1a231f209c3a372 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Sun, 16 May 2021 21:40:13 +0300 Subject: [PATCH 03/12] Add support for forms in root --- .../services/submit_form/configure.zcml | 4 +--- .../restapi/services/submit_form/post.py | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml b/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml index 25d3e6a3..fb88d28c 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml +++ b/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml @@ -16,10 +16,8 @@ method="POST" name="@submit-form" for="Products.CMFPlone.interfaces.siteroot.IPloneSiteRoot" - factory=".post.SubmitPost" + factory=".post.PloneSiteSubmitPost" permission="zope2.View" - layer="collective.volto.formsupport.interfaces.ICollectiveVoltoFormsupportLayer" /> - diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index 5769bb73..47a840df 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -14,6 +14,7 @@ from zope.interface import alsoProvides import codecs +import json import six @@ -251,3 +252,24 @@ def store_data(self): res = store.add(data=self.filter_parameters()) if not res: raise BadRequest("Unable to store data") + + +class PloneSiteSubmitPost(Service): + """Submit post service for plone root""" + + def get_block_data(self, block_id): + blocks = getattr(self.context, "blocks", {}) + if not blocks: + return {} + + if isinstance(blocks, str): + blocks = json.loads(blocks) + + for id, block in blocks.items(): + if id != block_id: + continue + block_type = block.get("@type", "") + if block_type != "form": + continue + return block + return {} From 60d2d9297bf4fc8f68603371341e37d806496825 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Mon, 17 May 2021 06:38:44 +0300 Subject: [PATCH 04/12] Add datastore adapter for root --- .../volto/formsupport/datamanager/catalog.py | 39 ++++++++++++++----- .../formsupport/datamanager/configure.zcml | 5 +++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/collective/volto/formsupport/datamanager/catalog.py b/src/collective/volto/formsupport/datamanager/catalog.py index bfe0a507..de3999a4 100644 --- a/src/collective/volto/formsupport/datamanager/catalog.py +++ b/src/collective/volto/formsupport/datamanager/catalog.py @@ -3,22 +3,20 @@ from copy import deepcopy from datetime import datetime from plone.dexterity.interfaces import IDexterityContent +from plone.i18n.normalizer.interfaces import IIDNormalizer from plone.restapi.deserializer import json_body +from Products.CMFPlone.interfaces.siteroot import IPloneSiteRoot from repoze.catalog.catalog import Catalog from repoze.catalog.indexes.field import CatalogFieldIndex from souper.interfaces import ICatalogFactory -from souper.soup import get_soup -from souper.soup import NodeAttributeIndexer -from souper.soup import Record -from zope.component import adapter -from zope.interface import implementer -from zope.interface import Interface -from zope.component import getUtility -from plone.i18n.normalizer.interfaces import IIDNormalizer - +from souper.soup import get_soup, NodeAttributeIndexer, Record +from zope.component import adapter, getUtility +from zope.interface import implementer, Interface +import json import logging + logger = logging.getLogger(__name__) @@ -111,3 +109,26 @@ def delete(self, id): def clear(self): self.soup.clear() + + +@implementer(IFormDataStore) +@adapter(IPloneSiteRoot, Interface) +class PloneSiteFormDataStore(FormDataStore): + def get_form_fields(self): + blocks = getattr(self.context, "blocks", {}) + if not blocks: + return {} + form_block = {} + + if isinstance(blocks, str): + blocks = json.loads(blocks) + + for id, block in blocks.items(): + if id != self.block_id: + continue + block_type = block.get("@type", "") + if block_type == "form": + form_block = deepcopy(block) + if not form_block: + return {} + return form_block.get("subblocks", []) diff --git a/src/collective/volto/formsupport/datamanager/configure.zcml b/src/collective/volto/formsupport/datamanager/configure.zcml index b492ad26..710d6b9c 100644 --- a/src/collective/volto/formsupport/datamanager/configure.zcml +++ b/src/collective/volto/formsupport/datamanager/configure.zcml @@ -8,6 +8,10 @@ + + + + + From 1f33af69c18a471f60ebd023d5123410169af574 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Mon, 24 May 2021 07:27:51 +0300 Subject: [PATCH 05/12] Use proper superclass for Plone root submit service --- .../volto/formsupport/datamanager/catalog.py | 1 + .../restapi/services/form_data/form_data.py | 10 +++------- .../formsupport/restapi/services/submit_form/post.py | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/collective/volto/formsupport/datamanager/catalog.py b/src/collective/volto/formsupport/datamanager/catalog.py index de3999a4..bf1e401b 100644 --- a/src/collective/volto/formsupport/datamanager/catalog.py +++ b/src/collective/volto/formsupport/datamanager/catalog.py @@ -115,6 +115,7 @@ def clear(self): @adapter(IPloneSiteRoot, Interface) class PloneSiteFormDataStore(FormDataStore): def get_form_fields(self): + # TODO: should this be getProperty? blocks = getattr(self.context, "blocks", {}) if not blocks: return {} diff --git a/src/collective/volto/formsupport/restapi/services/form_data/form_data.py b/src/collective/volto/formsupport/restapi/services/form_data/form_data.py index 159b9b8c..6873203e 100644 --- a/src/collective/volto/formsupport/restapi/services/form_data/form_data.py +++ b/src/collective/volto/formsupport/restapi/services/form_data/form_data.py @@ -4,10 +4,8 @@ from plone.restapi.interfaces import IExpandableElement from plone.restapi.serializer.converters import json_compatible from plone.restapi.services import Service -from zope.component import adapter -from zope.component import getMultiAdapter -from zope.interface import implementer -from zope.interface import Interface +from zope.component import adapter, getMultiAdapter +from zope.interface import implementer, Interface import json import six @@ -25,9 +23,7 @@ def __call__(self, expand=False): return {} result = { - "form_data": { - "@id": "{}/@form-data".format(self.context.absolute_url()) - } + "form_data": {"@id": "{}/@form-data".format(self.context.absolute_url())} } if not expand: return result diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index 47a840df..4d5c55aa 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -254,7 +254,7 @@ def store_data(self): raise BadRequest("Unable to store data") -class PloneSiteSubmitPost(Service): +class PloneSiteSubmitPost(SubmitPost): """Submit post service for plone root""" def get_block_data(self, block_id): From d63184596c892936efc148db3d36d961295c9f63 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Tue, 8 Jun 2021 09:54:24 +0300 Subject: [PATCH 06/12] Add inner blocks support --- .../volto/formsupport/datamanager/catalog.py | 26 ++++++++++++++++-- .../restapi/services/submit_form/post.py | 27 ++++++++++++++++--- src/collective/volto/formsupport/utils.py | 25 +++++++++++++++++ 3 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 src/collective/volto/formsupport/utils.py diff --git a/src/collective/volto/formsupport/datamanager/catalog.py b/src/collective/volto/formsupport/datamanager/catalog.py index bf1e401b..c2d1e7db 100644 --- a/src/collective/volto/formsupport/datamanager/catalog.py +++ b/src/collective/volto/formsupport/datamanager/catalog.py @@ -1,10 +1,13 @@ # -*- coding: utf-8 -*- + from collective.volto.formsupport.interfaces import IFormDataStore +from collective.volto.formsupport.utils import flatten_block_hierachy from copy import deepcopy from datetime import datetime from plone.dexterity.interfaces import IDexterityContent from plone.i18n.normalizer.interfaces import IIDNormalizer from plone.restapi.deserializer import json_body +from plone.restapi.slots.interfaces import ISlots from Products.CMFPlone.interfaces.siteroot import IPloneSiteRoot from repoze.catalog.catalog import Catalog from repoze.catalog.indexes.field import CatalogFieldIndex @@ -52,6 +55,15 @@ def get_form_fields(self): blocks = getattr(self.context, "blocks", {}) if not blocks: return {} + + slots = ISlots(self.context) + slot_names = slots.discover_slots() + + for name in slot_names: + flat = list((flatten_block_hierachy( + slots.get_blocks(name)['blocks'] or {}))) + blocks.update(flat) + form_block = {} for id, block in blocks.items(): if id != self.block_id: @@ -119,17 +131,27 @@ def get_form_fields(self): blocks = getattr(self.context, "blocks", {}) if not blocks: return {} - form_block = {} - if isinstance(blocks, str): blocks = json.loads(blocks) + slots = ISlots(self.context) + slot_names = slots.discover_slots() + + for name in slot_names: + flat = list((flatten_block_hierachy( + slots.get_blocks(name)['blocks'] or {}))) + blocks.update(flat) + + form_block = {} + for id, block in blocks.items(): if id != self.block_id: continue block_type = block.get("@type", "") if block_type == "form": form_block = deepcopy(block) + if not form_block: return {} + return form_block.get("subblocks", []) diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index 4d5c55aa..fdfce342 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -1,12 +1,14 @@ # -*- coding: utf-8 -*- from collective.volto.formsupport import _ from collective.volto.formsupport.interfaces import IFormDataStore +from collective.volto.formsupport.utils import flatten_block_hierachy from email.message import EmailMessage from plone import api from plone.protect.interfaces import IDisableCSRFProtection from plone.registry.interfaces import IRegistry from plone.restapi.deserializer import json_body from plone.restapi.services import Service +from plone.restapi.slots.interfaces import ISlots from Products.CMFPlone.interfaces.controlpanel import IMailSchema from zExceptions import BadRequest from zope.component import getMultiAdapter, getUtility @@ -94,8 +96,17 @@ def validate_form(self): def get_block_data(self, block_id): blocks = getattr(self.context, "blocks", {}) + slots = ISlots(self.context) + slot_names = slots.discover_slots() + + for name in slot_names: + flat = list((flatten_block_hierachy( + slots.get_blocks(name)['blocks'] or {}))) + blocks.update(flat) + if not blocks: return {} + for id, block in blocks.items(): if id != block_id: continue @@ -248,6 +259,8 @@ def manage_attachments(self, msg): ) def store_data(self): + import pdb + pdb.set_trace() store = getMultiAdapter((self.context, self.request), IFormDataStore) res = store.add(data=self.filter_parameters()) if not res: @@ -259,12 +272,20 @@ class PloneSiteSubmitPost(SubmitPost): def get_block_data(self, block_id): blocks = getattr(self.context, "blocks", {}) - if not blocks: - return {} - if isinstance(blocks, str): blocks = json.loads(blocks) + slots = ISlots(self.context) + slot_names = slots.discover_slots() + + for name in slot_names: + flat = list((flatten_block_hierachy( + slots.get_blocks(name)['blocks'] or {}))) + blocks.update(flat) + + if not blocks: + return {} + for id, block in blocks.items(): if id != block_id: continue diff --git a/src/collective/volto/formsupport/utils.py b/src/collective/volto/formsupport/utils.py new file mode 100644 index 00000000..20286b21 --- /dev/null +++ b/src/collective/volto/formsupport/utils.py @@ -0,0 +1,25 @@ +from collections import deque + + +def flatten_block_hierachy(blocks): + """ Given some blocks, return all contained blocks, including "subblocks" + + This allows embedding the form block into something like columns datastorage + """ + + queue = deque(list(blocks.items())) + + while queue: + blocktuple = queue.pop() + yield blocktuple + + block_value = blocktuple[1] + + if "data" in block_value: + if isinstance(block_value["data"], dict): + if "blocks" in block_value["data"]: + queue.extend(list( + block_value["data"]["blocks"].items())) + + if "blocks" in block_value: + queue.extend(list(block_value["blocks"].items())) From f91be0d50e31a26028a08c2e8a6ae7e0546109e0 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Tue, 8 Jun 2021 09:57:39 +0300 Subject: [PATCH 07/12] Remove pdb --- .../volto/formsupport/restapi/services/submit_form/post.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index fdfce342..0e0743b1 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -259,8 +259,6 @@ def manage_attachments(self, msg): ) def store_data(self): - import pdb - pdb.set_trace() store = getMultiAdapter((self.context, self.request), IFormDataStore) res = store.add(data=self.filter_parameters()) if not res: From 9680c990ce1aff8777429b83fc6f3a9c1d975cce Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Tue, 8 Jun 2021 11:33:51 +0300 Subject: [PATCH 08/12] Add fallback service for dxcontent --- .../restapi/services/submit_form/configure.zcml | 11 ++++++++++- .../formsupport/restapi/services/submit_form/post.py | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml b/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml index fb88d28c..5a435292 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml +++ b/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml @@ -16,8 +16,17 @@ method="POST" name="@submit-form" for="Products.CMFPlone.interfaces.siteroot.IPloneSiteRoot" - factory=".post.PloneSiteSubmitPost" + factory=".post.FallbackSubmitPost" permission="zope2.View" /> + + diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index 0e0743b1..2d2efe53 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -265,7 +265,7 @@ def store_data(self): raise BadRequest("Unable to store data") -class PloneSiteSubmitPost(SubmitPost): +class FallbackSubmitPost(SubmitPost): """Submit post service for plone root""" def get_block_data(self, block_id): From 33e629e9a2de35d2aa721b97938276be4919bf42 Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Wed, 28 Jul 2021 17:18:11 +0300 Subject: [PATCH 09/12] Update for new slots api --- .../volto/formsupport/datamanager/catalog.py | 28 ++++--------------- .../restapi/services/form_data/form_data.py | 12 ++++---- .../services/submit_form/configure.zcml | 2 +- .../restapi/services/submit_form/post.py | 25 ++--------------- src/collective/volto/formsupport/utils.py | 23 +++++++++++++++ 5 files changed, 38 insertions(+), 52 deletions(-) diff --git a/src/collective/volto/formsupport/datamanager/catalog.py b/src/collective/volto/formsupport/datamanager/catalog.py index c2d1e7db..11709117 100644 --- a/src/collective/volto/formsupport/datamanager/catalog.py +++ b/src/collective/volto/formsupport/datamanager/catalog.py @@ -1,13 +1,12 @@ # -*- coding: utf-8 -*- from collective.volto.formsupport.interfaces import IFormDataStore -from collective.volto.formsupport.utils import flatten_block_hierachy +from collective.volto.formsupport.utils import get_blocks from copy import deepcopy from datetime import datetime from plone.dexterity.interfaces import IDexterityContent from plone.i18n.normalizer.interfaces import IIDNormalizer from plone.restapi.deserializer import json_body -from plone.restapi.slots.interfaces import ISlots from Products.CMFPlone.interfaces.siteroot import IPloneSiteRoot from repoze.catalog.catalog import Catalog from repoze.catalog.indexes.field import CatalogFieldIndex @@ -16,7 +15,6 @@ from zope.component import adapter, getUtility from zope.interface import implementer, Interface -import json import logging @@ -52,18 +50,11 @@ def block_id(self): return data.get("block_id", "") def get_form_fields(self): - blocks = getattr(self.context, "blocks", {}) + blocks = get_blocks(self.context) + if not blocks: return {} - slots = ISlots(self.context) - slot_names = slots.discover_slots() - - for name in slot_names: - flat = list((flatten_block_hierachy( - slots.get_blocks(name)['blocks'] or {}))) - blocks.update(flat) - form_block = {} for id, block in blocks.items(): if id != self.block_id: @@ -128,19 +119,10 @@ def clear(self): class PloneSiteFormDataStore(FormDataStore): def get_form_fields(self): # TODO: should this be getProperty? - blocks = getattr(self.context, "blocks", {}) + blocks = get_blocks(self.context) + if not blocks: return {} - if isinstance(blocks, str): - blocks = json.loads(blocks) - - slots = ISlots(self.context) - slot_names = slots.discover_slots() - - for name in slot_names: - flat = list((flatten_block_hierachy( - slots.get_blocks(name)['blocks'] or {}))) - blocks.update(flat) form_block = {} diff --git a/src/collective/volto/formsupport/restapi/services/form_data/form_data.py b/src/collective/volto/formsupport/restapi/services/form_data/form_data.py index 6873203e..7f51f839 100644 --- a/src/collective/volto/formsupport/restapi/services/form_data/form_data.py +++ b/src/collective/volto/formsupport/restapi/services/form_data/form_data.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- + from collective.volto.formsupport.interfaces import IFormDataStore +from collective.volto.formsupport.utils import get_blocks from plone import api from plone.restapi.interfaces import IExpandableElement from plone.restapi.serializer.converters import json_compatible @@ -7,9 +9,6 @@ from zope.component import adapter, getMultiAdapter from zope.interface import implementer, Interface -import json -import six - @implementer(IExpandableElement) @adapter(Interface, Interface) @@ -46,14 +45,15 @@ def show_component(self): "Modify portal content", user=current, obj=self.context ): return False - blocks = getattr(self.context, "blocks", {}) - if isinstance(blocks, six.text_type): - blocks = json.loads(blocks) + blocks = get_blocks(self.context) + if not blocks: return False + for block in blocks.values(): if block.get("@type", "") == "form" and block.get("store", False): return True + return False def expand_records(self, record): diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml b/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml index 5a435292..e158d62a 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml +++ b/src/collective/volto/formsupport/restapi/services/submit_form/configure.zcml @@ -15,7 +15,7 @@ diff --git a/src/collective/volto/formsupport/restapi/services/submit_form/post.py b/src/collective/volto/formsupport/restapi/services/submit_form/post.py index 2d2efe53..aa5f5d3b 100644 --- a/src/collective/volto/formsupport/restapi/services/submit_form/post.py +++ b/src/collective/volto/formsupport/restapi/services/submit_form/post.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- from collective.volto.formsupport import _ from collective.volto.formsupport.interfaces import IFormDataStore -from collective.volto.formsupport.utils import flatten_block_hierachy +from collective.volto.formsupport.utils import get_blocks from email.message import EmailMessage from plone import api from plone.protect.interfaces import IDisableCSRFProtection from plone.registry.interfaces import IRegistry from plone.restapi.deserializer import json_body from plone.restapi.services import Service -from plone.restapi.slots.interfaces import ISlots from Products.CMFPlone.interfaces.controlpanel import IMailSchema from zExceptions import BadRequest from zope.component import getMultiAdapter, getUtility @@ -16,7 +15,6 @@ from zope.interface import alsoProvides import codecs -import json import six @@ -95,14 +93,7 @@ def validate_form(self): ) def get_block_data(self, block_id): - blocks = getattr(self.context, "blocks", {}) - slots = ISlots(self.context) - slot_names = slots.discover_slots() - - for name in slot_names: - flat = list((flatten_block_hierachy( - slots.get_blocks(name)['blocks'] or {}))) - blocks.update(flat) + blocks = get_blocks(self.context) if not blocks: return {} @@ -269,17 +260,7 @@ class FallbackSubmitPost(SubmitPost): """Submit post service for plone root""" def get_block_data(self, block_id): - blocks = getattr(self.context, "blocks", {}) - if isinstance(blocks, str): - blocks = json.loads(blocks) - - slots = ISlots(self.context) - slot_names = slots.discover_slots() - - for name in slot_names: - flat = list((flatten_block_hierachy( - slots.get_blocks(name)['blocks'] or {}))) - blocks.update(flat) + blocks = get_blocks(self.context) if not blocks: return {} diff --git a/src/collective/volto/formsupport/utils.py b/src/collective/volto/formsupport/utils.py index 20286b21..eb7cbbf3 100644 --- a/src/collective/volto/formsupport/utils.py +++ b/src/collective/volto/formsupport/utils.py @@ -1,4 +1,9 @@ from collections import deque +from plone.restapi.slots.interfaces import ISlots + +import copy +import json +import six def flatten_block_hierachy(blocks): @@ -23,3 +28,21 @@ def flatten_block_hierachy(blocks): if "blocks" in block_value: queue.extend(list(block_value["blocks"].items())) + + +def get_blocks(context): + """ Returns all blocks from a context, including those coming from slots + """ + blocks = copy.deepcopy(getattr(context, "blocks", {})) + if isinstance(blocks, six.text_type): + blocks = json.loads(blocks) + + slots = ISlots(context) + slot_names = slots.discover_slots() + + for name in slot_names: + flat = list((flatten_block_hierachy( + slots.get_data(name, full=True)['blocks'] or {}))) + blocks.update(flat) + + return blocks From 585d81770114e127ce9eb6296199a3c26f3e6aec Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Wed, 28 Jul 2021 22:51:26 +0300 Subject: [PATCH 10/12] WIP on new slot traversing support --- .../volto/formsupport/datamanager/catalog.py | 26 +++++++++++++++++++ .../formsupport/datamanager/configure.zcml | 1 + .../restapi/services/form_data/configure.zcml | 9 +++++++ src/collective/volto/formsupport/utils.py | 5 +++- 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/collective/volto/formsupport/datamanager/catalog.py b/src/collective/volto/formsupport/datamanager/catalog.py index 11709117..1a76bbff 100644 --- a/src/collective/volto/formsupport/datamanager/catalog.py +++ b/src/collective/volto/formsupport/datamanager/catalog.py @@ -7,6 +7,7 @@ from plone.dexterity.interfaces import IDexterityContent from plone.i18n.normalizer.interfaces import IIDNormalizer from plone.restapi.deserializer import json_body +from plone.restapi.slots.interfaces import ISlot from Products.CMFPlone.interfaces.siteroot import IPloneSiteRoot from repoze.catalog.catalog import Catalog from repoze.catalog.indexes.field import CatalogFieldIndex @@ -137,3 +138,28 @@ def get_form_fields(self): return {} return form_block.get("subblocks", []) + + +@implementer(IFormDataStore) +@adapter(ISlot, Interface) +class SlotDataStore(FormDataStore): + def get_form_fields(self): + # TODO: should this be getProperty? + blocks = get_blocks(self.context) + + if not blocks: + return {} + + form_block = {} + + for id, block in blocks.items(): + if id != self.block_id: + continue + block_type = block.get("@type", "") + if block_type == "form": + form_block = deepcopy(block) + + if not form_block: + return {} + + return form_block.get("subblocks", []) diff --git a/src/collective/volto/formsupport/datamanager/configure.zcml b/src/collective/volto/formsupport/datamanager/configure.zcml index 710d6b9c..bf50574f 100644 --- a/src/collective/volto/formsupport/datamanager/configure.zcml +++ b/src/collective/volto/formsupport/datamanager/configure.zcml @@ -21,4 +21,5 @@ + diff --git a/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml b/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml index 016aaf8c..92ea958c 100644 --- a/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml +++ b/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml @@ -12,6 +12,15 @@ layer="collective.volto.formsupport.interfaces.ICollectiveVoltoFormsupportLayer" /> + + Date: Thu, 29 Jul 2021 12:51:09 +0300 Subject: [PATCH 11/12] Support export/clear on plone root --- .../restapi/services/form_data/configure.zcml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml b/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml index 92ea958c..4f2b74bd 100644 --- a/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml +++ b/src/collective/volto/formsupport/restapi/services/form_data/configure.zcml @@ -41,6 +41,15 @@ layer="collective.volto.formsupport.interfaces.ICollectiveVoltoFormsupportLayer" /> + + + + From 64d70dd3037783d9d5c9499b9c9796a93392e65a Mon Sep 17 00:00:00 2001 From: Tiberiu Ichim Date: Sat, 21 Oct 2023 19:44:28 +0300 Subject: [PATCH 12/12] Fix upgrade when portal has blocks in native format --- src/collective/volto/formsupport/upgrades.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/collective/volto/formsupport/upgrades.py b/src/collective/volto/formsupport/upgrades.py index 1ae3aff8..4f9ce801 100644 --- a/src/collective/volto/formsupport/upgrades.py +++ b/src/collective/volto/formsupport/upgrades.py @@ -1,15 +1,15 @@ # -*- coding: utf-8 -*- from Acquisition import aq_base +from collective.volto.formsupport.interfaces import IFormDataStore from copy import deepcopy from plone import api from plone.dexterity.utils import iterSchemata -from zope.schema import getFields -from collective.volto.formsupport.interfaces import IFormDataStore -from zope.component import getMultiAdapter -from zope.globalrequest import getRequest +from plone.i18n.normalizer.interfaces import IIDNormalizer from souper.soup import Record +from zope.component import getMultiAdapter from zope.component import getUtility -from plone.i18n.normalizer.interfaces import IIDNormalizer +from zope.globalrequest import getRequest +from zope.schema import getFields try: @@ -129,7 +129,10 @@ def fix_data(blocks, context): portal = api.portal.get() portal_blocks = getattr(portal, "blocks", "") if portal_blocks: - blocks = json.loads(portal_blocks) + if isinstance(portal_blocks, str): + blocks = json.loads(portal_blocks) + else: + blocks = portal_blocks res = fix_data(blocks, portal) if res: fixed_contents.append("/")