diff --git a/CHANGES.rst b/CHANGES.rst
index 3b1fa43..1dedccc 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,7 +4,8 @@ Changelog
5.5.8 (unreleased)
------------------
-- Nothing changed yet.
+- Add linkintegrity indexers for some custom blocks.
+ [cekk]
5.5.7 (2024-10-28)
diff --git a/src/redturtle/volto/adapters/blocks_linkintegrity.py b/src/redturtle/volto/adapters/blocks_linkintegrity.py
index 7fd9a86..a52b616 100644
--- a/src/redturtle/volto/adapters/blocks_linkintegrity.py
+++ b/src/redturtle/volto/adapters/blocks_linkintegrity.py
@@ -1,93 +1,33 @@
-from collective.volto.blocksfield.field import BlocksField
-from plone.app.linkintegrity.interfaces import IRetriever
-from plone.app.linkintegrity.parser import extractLinks
-from plone.app.textfield import RichText
-from plone.dexterity.interfaces import IDexterityContainer
from plone.dexterity.interfaces import IDexterityContent
-from plone.dexterity.interfaces import IDexterityFTI
-from plone.dexterity.interfaces import IDexterityItem
-from plone.dexterity.utils import getAdditionalSchemata
-from plone.restapi.blocks import iter_block_transform_handlers
-from plone.restapi.blocks import visit_blocks
-from plone.restapi.blocks_linkintegrity import BlocksRetriever as BaseBlocksRetriever
from plone.restapi.blocks_linkintegrity import (
GenericBlockLinksRetriever as BaseGenericBlockLinksRetriever,
-)
-from plone.restapi.blocks_linkintegrity import (
- SlateBlockLinksRetriever as BaseSlateBlockLinksRetriever,
-)
-from plone.restapi.blocks_linkintegrity import (
+ SlateBlockLinksRetriever,
TextBlockLinksRetriever as BaseTextBlockLinksRetriever,
+ get_urls_from_value,
)
+from plone.restapi.deserializer.blocks import iterate_children
from plone.restapi.interfaces import IBlockFieldLinkIntegrityRetriever
from redturtle.volto.interfaces import IRedturtleVoltoLayer
from zope.component import adapter
-from zope.component import getUtility
from zope.interface import implementer
-from zope.schema import getFieldsInOrder
-
-
-class BaseRTRetriever(BaseBlocksRetriever):
- def retrieveLinks(self):
- """
- Check links in:
- - blocks field
- - text fields
- - BlocksField fields
- """
- # first do plone.restapi links generation
- links = super().retrieveLinks()
-
- # then iterate over content schema and check for other references
- fti = getUtility(IDexterityFTI, name=self.context.portal_type)
- schema = fti.lookupSchema()
- additional_schema = getAdditionalSchemata(
- context=self.context, portal_type=self.context.portal_type
- )
- schemas = [i for i in additional_schema] + [schema]
- links = set()
- for schema in schemas:
- for name, field in getFieldsInOrder(schema):
- if isinstance(field, RichText):
- value = getattr(schema(self.context), name)
- if not value or not getattr(value, "raw", None):
- continue
- links |= set(extractLinks(value.raw))
- elif isinstance(field, BlocksField):
- value = field.get(self.context)
- if not value:
- continue
- if not isinstance(value, dict):
- continue
- blocks = value.get("blocks", {})
- if not blocks:
- continue
- for block in visit_blocks(self.context, blocks):
- for handler in iter_block_transform_handlers(
- self.context, block, IBlockFieldLinkIntegrityRetriever
- ):
- links |= set(handler(block))
- return links
-
-
-@implementer(IRetriever)
-@adapter(IDexterityItem)
-class BlocksRetrieverItem(BaseRTRetriever):
- """
- Retriever for Item contents.
- Needed a more specific than IDexterityContent because it's already registered.
- """
-
-
-@implementer(IRetriever)
-@adapter(IDexterityContainer)
-class BlocksRetrieverContainer(BaseRTRetriever):
- """
- Retriever for Container contents.
- Needed a more specific than IDexterityContent because it's already registered.
- """
+from zope.publisher.interfaces.browser import IBrowserRequest
+
+
+class SubBlocksRetriever(SlateBlockLinksRetriever):
+
+ def extract_links(self, block_data):
+ children = iterate_children(block_data or [])
+ for child in children:
+ node_type = child.get("type")
+ if node_type:
+ handler = getattr(self, f"handle_{node_type}", None)
+ if handler:
+ value = handler(child)
+ if value:
+ self.links.append(value)
+# Specific blocks adapters
@adapter(IDexterityContent, IRedturtleVoltoLayer)
@implementer(IBlockFieldLinkIntegrityRetriever)
class TextBlockLinksRetriever(BaseTextBlockLinksRetriever):
@@ -96,7 +36,7 @@ class TextBlockLinksRetriever(BaseTextBlockLinksRetriever):
@adapter(IDexterityContent, IRedturtleVoltoLayer)
@implementer(IBlockFieldLinkIntegrityRetriever)
-class SlateBlockLinksRetriever(BaseSlateBlockLinksRetriever):
+class RTSlateBlockLinksRetriever(SlateBlockLinksRetriever):
"""Retriever for slate blocks"""
@@ -104,3 +44,135 @@ class SlateBlockLinksRetriever(BaseSlateBlockLinksRetriever):
@implementer(IBlockFieldLinkIntegrityRetriever)
class GenericBlockLinksRetriever(BaseGenericBlockLinksRetriever):
"""Retriever for generic blocks"""
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class SimpleCardBlockLinksRetriever(SlateBlockLinksRetriever):
+ order = 200
+ block_type = "testo_riquadro_semplice"
+ field = "simple_card_content"
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class AccordionBlockLinksRetriever(SubBlocksRetriever):
+ order = 200
+ block_type = "accordion"
+
+ def __call__(self, block):
+ if not block:
+ return self.links
+ description = block.get("description", [])
+ self.extract_links(block_data=description)
+
+ for subblock in block.get("subblocks", []):
+ self.extract_links(block_data=subblock.get("text", {}))
+
+ return self.links
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class AlertBlockLinksRetriever(SlateBlockLinksRetriever):
+ order = 200
+ block_type = "alert"
+ field = "text"
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class ImageCardBlockLinksRetriever(SlateBlockLinksRetriever):
+ order = 200
+ block_type = "testo_riquadro_immagine"
+ field = "image_card_content"
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class CalloutBlockLinksRetriever(SlateBlockLinksRetriever):
+ order = 200
+ block_type = "callout_block"
+ field = "text"
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class CTABlockLinksRetriever(SlateBlockLinksRetriever):
+ order = 200
+ block_type = "cta_block"
+ field = "cta_content"
+
+ def __call__(self, block):
+ super().__call__(block=block)
+
+ for url in get_urls_from_value(block.get("ctaLink", "")):
+ self.links.append(url)
+ for img in block.get("ctaImage", []):
+ self.links.append(f"resolveuid/{img}")
+
+ return self.links
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class TableBlockLinksRetriever(SubBlocksRetriever):
+ order = 200
+ block_type = "slateTable"
+
+ def __call__(self, block):
+ if not block:
+ return self.links
+
+ for row in block.get("table", {}).get("rows", []):
+ for cell in row.get("cells", []):
+
+ self.extract_links(block_data=cell.get("value", {}))
+
+ return self.links
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class ContactsBlockLinksRetriever(SubBlocksRetriever):
+ order = 200
+ block_type = "contacts"
+
+ def __call__(self, block):
+ if not block:
+ return self.links
+ description = block.get("description", [])
+ self.extract_links(block_data=description)
+
+ for subblock in block.get("subblocks", []):
+ self.extract_links(block_data=subblock.get("text", {}))
+ self.extract_links(block_data=subblock.get("tel", {}))
+ self.extract_links(block_data=subblock.get("email", {}))
+
+ return self.links
+
+
+@adapter(IDexterityContent, IBrowserRequest)
+@implementer(IBlockFieldLinkIntegrityRetriever)
+class IconBlockLinksRetriever(SubBlocksRetriever):
+ order = 200
+ block_type = "iconBlocks"
+
+ def __call__(self, block):
+ if not block:
+ return self.links
+ description = block.get("description", [])
+ self.extract_links(block_data=description)
+
+ for url in get_urls_from_value(block.get("href", "")):
+ self.links.append(url)
+
+ for img in block.get("background", []):
+ self.links.append(f"resolveuid/{img}")
+
+ for subblock in block.get("subblocks", []):
+ self.extract_links(block_data=subblock.get("text", {}))
+ for url in get_urls_from_value(subblock.get("href", "")):
+ self.links.append(url)
+
+ return self.links
diff --git a/src/redturtle/volto/adapters/blocks_linkintegrity_blocksfield.py b/src/redturtle/volto/adapters/blocks_linkintegrity_blocksfield.py
new file mode 100644
index 0000000..4fbf911
--- /dev/null
+++ b/src/redturtle/volto/adapters/blocks_linkintegrity_blocksfield.py
@@ -0,0 +1,77 @@
+from collective.volto.blocksfield.field import BlocksField
+from plone.app.linkintegrity.interfaces import IRetriever
+from plone.app.linkintegrity.parser import extractLinks
+from plone.app.textfield import RichText
+from plone.dexterity.interfaces import IDexterityContainer
+from plone.dexterity.interfaces import IDexterityFTI
+from plone.dexterity.interfaces import IDexterityItem
+from plone.dexterity.utils import getAdditionalSchemata
+from plone.restapi.blocks import iter_block_transform_handlers
+from plone.restapi.blocks import visit_blocks
+from plone.restapi.blocks_linkintegrity import BlocksRetriever as BaseBlocksRetriever
+from plone.restapi.interfaces import IBlockFieldLinkIntegrityRetriever
+from zope.component import adapter
+from zope.component import getUtility
+from zope.interface import implementer
+from zope.schema import getFieldsInOrder
+
+
+class BaseRTRetriever(BaseBlocksRetriever):
+ def retrieveLinks(self):
+ """
+ Check links in:
+ - blocks field
+ - text fields
+ - BlocksField fields
+ """
+ # first do plone.restapi links generation
+ links = super().retrieveLinks()
+
+ # then iterate over content schema and check for other references
+ fti = getUtility(IDexterityFTI, name=self.context.portal_type)
+ schema = fti.lookupSchema()
+ additional_schema = getAdditionalSchemata(
+ context=self.context, portal_type=self.context.portal_type
+ )
+ schemas = [i for i in additional_schema] + [schema]
+ links = set()
+ for schema in schemas:
+ for name, field in getFieldsInOrder(schema):
+ if isinstance(field, RichText):
+ value = getattr(schema(self.context), name)
+ if not value or not getattr(value, "raw", None):
+ continue
+ links |= set(extractLinks(value.raw))
+ elif isinstance(field, BlocksField):
+ value = field.get(self.context)
+ if not value:
+ continue
+ if not isinstance(value, dict):
+ continue
+ blocks = value.get("blocks", {})
+ if not blocks:
+ continue
+ for block in visit_blocks(self.context, blocks):
+ for handler in iter_block_transform_handlers(
+ self.context, block, IBlockFieldLinkIntegrityRetriever
+ ):
+ links |= set(handler(block))
+ return links
+
+
+@implementer(IRetriever)
+@adapter(IDexterityItem)
+class BlocksRetrieverItem(BaseRTRetriever):
+ """
+ Retriever for Item contents.
+ Needed a more specific than IDexterityContent because it's already registered.
+ """
+
+
+@implementer(IRetriever)
+@adapter(IDexterityContainer)
+class BlocksRetrieverContainer(BaseRTRetriever):
+ """
+ Retriever for Container contents.
+ Needed a more specific than IDexterityContent because it's already registered.
+ """
diff --git a/src/redturtle/volto/adapters/configure.zcml b/src/redturtle/volto/adapters/configure.zcml
index a2ada52..c7f8ec8 100644
--- a/src/redturtle/volto/adapters/configure.zcml
+++ b/src/redturtle/volto/adapters/configure.zcml
@@ -20,11 +20,12 @@
-
-
-
+
+
+
-
+
@@ -33,11 +34,46 @@
provides="plone.restapi.interfaces.IBlockFieldLinkIntegrityRetriever"
/>
-
-
+
+
+
+
+
+
+
+
+
+