Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix serializer/deserializer for footerTop blocks: use blocks handlers… #8

Merged
merged 7 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ jobs:
max-parallel: 4
matrix:
python: ["3.8", "3.9", "3.10", "3.11"]
plone: ["52", "60"]
exclude:
- python: "3.10"
plone: "52"
- python: "3.11"
plone: "52"
plone: ["60"]
# exclude:
# - python: "3.10"
# plone: "52"
# - python: "3.11"
# plone: "52"
steps:
- uses: actions/checkout@v3
- name: Cache eggs
Expand Down
3 changes: 2 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Changelog
1.3.3 (unreleased)
------------------

- Nothing changed yet.
- Fix serializer/deserializer for footerTop blocks: use blocks handlers to fix data.
[cekk]


1.3.2 (2024-03-14)
Expand Down
2 changes: 1 addition & 1 deletion base.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ recipe = plone.recipe.codeanalysis
directory = ${buildout:directory}/src
flake8-exclude=bootstrap.py,bootstrap-buildout.py,docs,bin,*.egg,setup.py,overrides,omelette
flake8-max-complexity = 25
flake8-ignore = E203, E266, E501, W503, E999
flake8-ignore = E203, E266, E501, W503, E999, C101
flake8-max-line-length = 200
# flake8-select = B,C,E,F,W,T4,B9
flake8-extensions =
Expand Down
12 changes: 4 additions & 8 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ ignore =
.gitattributes

[isort]
# for details see
# http://docs.plone.org/develop/styleguide/python.html#grouping-and-sorting
force_alphabetical_sort = True
force_single_line = True
lines_after_imports = 2
line_length = 200
not_skip = __init__.py
# black compatible isort rules:
profile = plone

[flake8]
# black compatible flake8 rules:
Expand All @@ -22,10 +17,11 @@ ignore =
E501
T001
C813
C101
# E203, E266
exclude = bootstrap.py,docs,*.egg.,omelette
max-line-length = 88
max-complexity = 18
select = B,C,E,F,W,T4,B9
builtins = unicode,basestring

builtins = unicode,basestring
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-
from plone.app.registry.browser import controlpanel
from redturtle.voltoplugin.editablefooter.interfaces import (
IEditableFooterSettings,
)
from redturtle.voltoplugin.editablefooter import _
from redturtle.voltoplugin.editablefooter.interfaces import IEditableFooterSettings


class EditableFooterForm(controlpanel.RegistryEditForm):
Expand Down
14 changes: 14 additions & 0 deletions src/redturtle/voltoplugin/editablefooter/restapi/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from plone.restapi.blocks import iter_block_transform_handlers
from plone.restapi.blocks import visit_blocks


def fix_footer_top_blocks(context, blocks, transformer):
if not blocks:
return blocks
for block in visit_blocks(context, blocks):
new_block = block.copy()
for handler in iter_block_transform_handlers(context, block, transformer):
new_block = handler(new_block)
block.clear()
block.update(new_block)
return blocks
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
from plone.restapi.controlpanels import RegistryConfigletPanel
from redturtle.voltoplugin.editablefooter.interfaces import IEditableFooterSettings
from redturtle.voltoplugin.editablefooter.interfaces import (
IRedturtleVoltoEditablefooterLayer,
IEditableFooterSettings,
)
from zope.component import adapter
from zope.interface import implementer
Expand Down
45 changes: 37 additions & 8 deletions src/redturtle/voltoplugin/editablefooter/restapi/deserializer.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# -*- coding: utf-8 -*-
from plone import api
from plone.restapi.deserializer import json_body
from plone.restapi.deserializer.controlpanels import (
ControlpanelDeserializeFromJson,
)
from plone.restapi.deserializer.controlpanels import ControlpanelDeserializeFromJson
from plone.restapi.interfaces import IBlockFieldDeserializationTransformer
from plone.restapi.interfaces import IDeserializeFromJson
from redturtle.voltoplugin.editablefooter.interfaces import (
IEditableFooterSettings,
)
from redturtle.voltoplugin.editablefooter import _
from redturtle.voltoplugin.editablefooter.interfaces import IEditableFooterSettings
from redturtle.voltoplugin.editablefooter.restapi import fix_footer_top_blocks
from zExceptions import BadRequest
from zope.component import adapter
from zope.interface import implementer
Expand All @@ -21,10 +21,39 @@ def __call__(self):
req = json_body(self.controlpanel.request)
proxy = self.registry.forInterface(self.schema, prefix=self.schema_prefix)
errors = []
data = req.get("footer_columns", {})
data = req.get("footer_columns", [])
if not data:
errors.append({"message": "Missing data", "field": "footer_columns"})
errors.append(
{
"message": api.portal.translate(
_("missing_data_label", default="Missing data")
),
"field": "footer_columns",
}
)
raise BadRequest(errors)
if not isinstance(data, list):
errors.append(
{
"message": api.portal.translate(
_(
"wrong_type_data_label",
default="Wrong type: need to be a list of values",
)
),
"field": "footer_columns",
}
)
raise BadRequest(errors)
for path_setting in data:
footer_top = path_setting.get("footerTop", {}).get("blocks", {})
if footer_top:
path_setting["footerTop"]["blocks"] = fix_footer_top_blocks(
context=self.context,
blocks=footer_top,
transformer=IBlockFieldDeserializationTransformer,
)

try:
# later we need to do some validations
setattr(proxy, "footer_columns", json.dumps(data))
Expand Down
21 changes: 14 additions & 7 deletions src/redturtle/voltoplugin/editablefooter/restapi/get.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# -*- coding: utf-8 -*-
from redturtle.voltoplugin.editablefooter.interfaces import (
IEditableFooterSettings,
)
from plone import api
from plone.registry.interfaces import IRegistry
from plone.restapi.interfaces import IBlockFieldSerializationTransformer
from plone.restapi.serializer.converters import json_compatible
from plone.restapi.services import Service
from redturtle.voltoplugin.editablefooter.interfaces import IEditableFooterSettings
from redturtle.voltoplugin.editablefooter.restapi import fix_footer_top_blocks
from zope.component import getUtility
from zope.interface import implementer
from zope.publisher.interfaces import IPublishTraverse


try:
from plone.volto.interfaces import IVoltoSettings

Expand All @@ -21,9 +23,6 @@

@implementer(IPublishTraverse)
class FooterColumns(Service):
def __init__(self, context, request):
super(FooterColumns, self).__init__(context, request)

def reply(self):
record = api.portal.get_registry_record(
"footer_columns", interface=IEditableFooterSettings, default=""
Expand All @@ -34,6 +33,14 @@ def reply(self):
portal_url = self.get_portal_url()
for el in data or []:
if isinstance(el, dict):
footer_top = el.get("footerTop", {}).get("blocks", {})
if footer_top:
el["footerTop"]["blocks"] = fix_footer_top_blocks(
context=self.context,
blocks=footer_top,
transformer=IBlockFieldSerializationTransformer,
)

for item in el.get("items") or []:
if (
isinstance(item, dict)
Expand All @@ -44,7 +51,7 @@ def reply(self):
item["text"]["data"] = item["text"]["data"].replace(
'href="/', f'href="{portal_url}/'
)
return data
return json_compatible(data)

def get_portal_url(self):
portal_url = api.portal.get().absolute_url()
Expand Down
25 changes: 19 additions & 6 deletions src/redturtle/voltoplugin/editablefooter/restapi/serializer.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# -*- coding: utf-8 -*-
from redturtle.voltoplugin.editablefooter.interfaces import (
IEditableFooterSettings,
)
from plone import api
from plone.restapi.interfaces import IBlockFieldSerializationTransformer
from plone.restapi.interfaces import ISerializeToJson
from plone.restapi.serializer.controlpanels import ControlpanelSerializeToJson
from redturtle.voltoplugin.editablefooter.interfaces import IEditableFooterSettings
from redturtle.voltoplugin.editablefooter.restapi import fix_footer_top_blocks
from zope.component import adapter
from zope.interface import implementer

Expand All @@ -14,8 +15,20 @@
@adapter(IEditableFooterSettings)
class EditableFooterControlpanelSerializeToJson(ControlpanelSerializeToJson):
def __call__(self):
json_data = super(EditableFooterControlpanelSerializeToJson, self).__call__()
json_data = super().__call__()
conf = json_data["data"].get("footer_columns", "")
if conf:
json_data["data"]["footer_columns"] = json.loads(conf)
if not conf:
return json_data
footer_columns = json.loads(conf)

for path_setting in footer_columns:
footer_top = path_setting.get("footerTop", {}).get("blocks", {})
if footer_top:
path_setting["footerTop"]["blocks"] = fix_footer_top_blocks(
context=api.portal.get(),
blocks=footer_top,
transformer=IBlockFieldSerializationTransformer,
)

json_data["data"]["footer_columns"] = footer_columns
return json_data
2 changes: 1 addition & 1 deletion src/redturtle/voltoplugin/editablefooter/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
from plone.restapi.testing import PloneRestApiDXLayer
from plone.testing import z2

import redturtle.voltoplugin.editablefooter
import plone.restapi
import plone.volto
import redturtle.voltoplugin.editablefooter


class VoltoEditableFooterLayer(PloneSandboxLayer):
Expand Down
Loading
Loading