Skip to content

Instantly share code, notes, and snippets.

@cdw9
Last active May 21, 2024 19:43
Show Gist options
  • Save cdw9/238c4e8b296264c21dd98e7295d202b4 to your computer and use it in GitHub Desktop.
Save cdw9/238c4e8b296264c21dd98e7295d202b4 to your computer and use it in GitHub Desktop.
Mosaic Link Integrity - A subscriber that will gather all links and references from tiles to store them and properly connect the objects
<subscriber
for="plone.dexterity.interfaces.IDexterityContent
zope.lifecycleevent.interfaces.IObjectModifiedEvent"
handler=".events.modifiedMosaic"
/>
import Acquisition
from plone import api
from plone.app.blocks import layoutbehavior
from plone.app.blocks import utils as blocks_utils
from plone.app.linkintegrity.handlers import (
check_linkintegrity_dependencies,
getObjectsFromLinks,
updateReferences)
from plone.app.linkintegrity.parser import extractLinks
from plone.tiles.interfaces import ITileDataManager
from plone.transformchain import zpublisher
from repoze.xmliter import utils as xmliter_utils
from six.moves import urllib
from Testing.makerequest import makerequest
from zope import interface
# tile fields to check
# 'richtext': is a RichTextValue object
# 'reference': uses RelatedItemsFieldWidget, is a UID
# 'path': uses LinkFieldWidget, is a path
TILE_FIELDS = {
'text': 'richtext',
'cta_text': 'richtext',
'banner_desc': 'richtext',
'content': 'richtext',
'image': 'reference',
'cta_link': 'path',
'button_link': 'path',
}
def getObjTiles(obj):
""" get all tiles from a Mosaic object """
request = obj.REQUEST
lookup = layoutbehavior.ILayoutAware(obj, None)
layout = lookup.content_layout() if lookup else None
encoding = zpublisher.extractEncoding(request.response)
serializer = xmliter_utils.getHTMLSerializer(
[layout], encoding=encoding)
app = makerequest(
Acquisition.aq_base(obj.getPhysicalRoot()))
interface.alsoProvides(
app.REQUEST, *interface.providedBy(request))
tiles = []
for tileNode in blocks_utils.bodyTileXPath(serializer.tree):
data_tile = urllib.parse.urlsplit(
tileNode.attrib[blocks_utils.tileAttrib])
tile_path = data_tile.path[2:]
tile = obj.restrictedTraverse(tile_path)
dataManager = ITileDataManager(tile).storage
if getattr(dataManager, 'tile', None):
tiles.append(dataManager.tile)
return tiles
def getTileLinks(tile):
""" return a set of links as paths and a set of RelationValue objects """
tile_links = set()
for field in TILE_FIELDS.keys():
value = tile.get(field, None)
if not value:
continue
type = TILE_FIELDS[field]
if type == 'richtext':
if getattr(value, 'raw', None):
value = value.raw
tile_links |= set(extractLinks(value))
elif type == 'reference':
try:
ref_path = ("/").join(api.content.get(UID=value).getPhysicalPath())
except Exception as e:
continue
tile_links.add(ref_path)
elif type == 'path':
tile_links.add(value)
return tile_links
def modifiedMosaic(obj, event):
""" a Mosaic object was modified
this is based on plone.app.linkintegrity's modifiedContent
"""
if 'layout' not in obj.defaultView() or not check_linkintegrity_dependencies(obj):
return
tiles = getObjTiles(obj)
links = set()
for tile in tiles:
tile_links = getTileLinks(tile.data)
links |= tile_links
refs = getObjectsFromLinks(obj, links)
updateReferences(obj, refs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment