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 importing blocks on the root #56

Merged
merged 4 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions news/56.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix importing blocks on the site-root.
[pbauer]
3 changes: 0 additions & 3 deletions src/plone/distribution/exportimport/dist_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,4 @@ def global_dict_hook(self, item: dict, obj: DexterityContent) -> dict:
if item["@type"] == "Plone Site":
# To avoid a conflict between @id and id
item["@id"] = f"/{item['id']}"
if "blocks" in item:
blocks = item["blocks"]
item["blocks"] = helpers.parse_blocks(blocks)
return item
32 changes: 29 additions & 3 deletions src/plone/distribution/exportimport/dist_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
from collective.exportimport.import_content import ImportContent as BaseImportView
from pathlib import Path
from plone import api
from plone.dexterity.content import DexterityContent
from plone.dexterity.interfaces import IDexterityFTI
from plone.distribution import logger
from plone.distribution.exportimport import helpers
from plone.distribution.exportimport.interfaces import ExportFormat
from Products.Five import BrowserView
from typing import List
from zope.component import queryUtility


class ImportAll(BrowserView):
Expand Down Expand Up @@ -76,7 +79,7 @@ def __call__(
iterator=None,
server_directory=False,
):
self.portal_uid = api.content.get_uuid(api.portal.get())
self.portal = api.portal.get()
self.default_language = api.portal.get_registry_record(
"plone.default_language", default="en"
)
Expand All @@ -91,10 +94,33 @@ def __call__(
)

def global_dict_hook(self, item: dict) -> dict:
if item["@type"] == "Plone Site":
item["UID"] = self.portal_uid
# Fix Language
current = item.get("language")
if current not in self.languages:
item["language"] = self.default_language
return item

def dict_hook_plonesite(self, item: dict) -> dict:
"""The Plone Site object exists already so it is updated.
We keep id and UID of the existing object."""
item["UID"] = api.content.get_uuid(obj=self.portal)
item["@id"] = f"/{self.portal.id}"
item["id"] = self.portal.id
item["title"] = self.portal.title
item["description"] = self.portal.description
return item

def obj_hook_plonesite(self, obj: DexterityContent, item: dict) -> None:
"""IBlocks(obj) does not work yet at this point, so we have to
force the blocks onto the object if Plone Site has the behavior.
"""
fti = queryUtility(IDexterityFTI, name="Plone Site")
if (
fti
and "volto.blocks" in fti.behaviors
and "blocks" in item
and "blocks_layout" in item
):
obj.blocks = item["blocks"]
obj.blocks_layout = item["blocks_layout"]
return
43 changes: 0 additions & 43 deletions src/plone/distribution/exportimport/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,49 +61,6 @@ def remove_site_root(item: dict, portal_url: str) -> dict:
return json.loads(item_str)


def _fix_image_paths(data: list) -> list:
"""Rewrite image urls to use the scale name.

This is not ideal in terms of performance, but
it 'works' for imported content.
"""
parsed = []
for info in data:
image_scales = info["image_scales"]
for field in image_scales:
field_data = image_scales[field][0]
field_data["download"] = f"@@images/{field}"
for key, scale in field_data["scales"].items():
scale["download"] = f"@@images/{field}/{key}"
parsed.append(info)
return parsed


def _fix_grid_block(block: dict) -> dict:
"""Remove references to computed scales in images."""
for column in block["columns"]:
for key in ("preview_image", "image"):
image_data = column.get(key)
if not image_data:
continue
column[key] = _fix_image_paths(image_data)
return block


BLOCKS_HANDLERS = {"__grid": _fix_grid_block}


def parse_blocks(blocks: dict) -> dict:
"""Clean up blocks."""
parsed = {}
for block_uid, block in blocks.items():
type_ = block.get("@type")
func = BLOCKS_HANDLERS.get(type_, None)
block = func(block) if func else block
parsed[block_uid] = block
return parsed


def exports_for_distribution(distribution: Distribution) -> List[ExportStep]:
"""Return a list of available exports for a given distribution."""
_exports = []
Expand Down
7 changes: 1 addition & 6 deletions tests/api/test_api_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class TestApiSite:
def test_get_sites(self, app, integration):
sites = site_api.get_sites(app)
# Integration test creates a Plone Site
assert len(sites) == 3
assert len(sites) == 2
site = sites[0]
assert isinstance(site, PloneSite)

Expand All @@ -54,11 +54,6 @@ def test_create(self, app, integration, answers, distribution_name):
assert isinstance(site, PloneSite)
assert site.title == new_site.title

def test_get_creation_report_old_site(self, app, integration):
# An existing site (or older distribution will not have a report)
report = site_api.get_creation_report(app.Plone)
assert report is None

def test_get_creation_report_new_site(self, site):
from datetime import datetime
from plone.distribution.core import SiteCreationReport
Expand Down
20 changes: 0 additions & 20 deletions tests/exportimport/test_exportimport_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,3 @@ def test_remove_site_root_from_image_block(self, integration, export_item):
result = func(export_item, self.SITE_ROOT)
result_block = self._get_img_block(result)
assert result_block["url"].startswith("/")

def test__fix_grid_block(self, integration, export_item):
func = helpers._fix_grid_block
grid_block = self._get_grid_block(export_item)
src_column = self._get_grid_block_column(grid_block)
src_img_scale = src_column["preview_image"][0]["image_scales"]["image"][0]
assert (
src_img_scale["download"]
== "@@images/image-2048-4b3f8a97eb42b769ee35ed55a3e962b0.png"
)
assert (
src_img_scale["scales"]["great"]["download"]
== "@@images/image-1200-bd0038e8561f6da7a065b2866232fee1.png"
)

result = func(grid_block)
result_column = self._get_grid_block_column(result)
result_img_scale = result_column["preview_image"][0]["image_scales"]["image"][0]
assert result_img_scale["download"] == "@@images/image"
assert result_img_scale["scales"]["great"]["download"] == "@@images/image/great"
2 changes: 1 addition & 1 deletion tests/services/test_services_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_sites_get_sites(self, app):
data = response.json()
sites = data["sites"]
assert isinstance(sites, list)
assert len(sites) == 3
assert len(sites) == 2
assert sites[0]["id"] == "plone"
assert sites[0]["needs_upgrade"] is False

Expand Down