-
-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Centralize logic for finding all blocks (#1648)
* Centralize block visiting logic * use generator instead of callback * lint * fix zcml for Plone 5 * fix types * remove unused imports * Use block visitors for SearchableText indexing * Depth-first traversal, to match existing behavior * changelog * test that visit_blocks returns blocks in the expected order * docs
- Loading branch information
Showing
11 changed files
with
200 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Add `visit_blocks` util for finding all nested blocks. @davisagli |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from zope.component import adapter | ||
from zope.component import subscribers | ||
from zope.interface import implementer | ||
from zope.interface import Interface | ||
from zope.globalrequest import getRequest | ||
from zope.publisher.interfaces.browser import IBrowserRequest | ||
from plone.restapi.interfaces import IBlockVisitor | ||
|
||
|
||
def visit_blocks(context, blocks): | ||
"""Generator yielding all blocks, including nested blocks. | ||
context: Content item where these blocks are stored. | ||
blocks: A dict mapping block ids to a dict of block data. | ||
""" | ||
request = getRequest() | ||
visitors = subscribers((context, request), IBlockVisitor) | ||
|
||
def _visit_subblocks(block): | ||
for visitor in visitors: | ||
for subblock in visitor(block): | ||
yield from _visit_subblocks(subblock) | ||
yield block | ||
|
||
for block in blocks.values(): | ||
yield from _visit_subblocks(block) | ||
|
||
|
||
def visit_subblocks(context, block): | ||
"""Generator yielding the immediate subblocks of a block. | ||
context: Context item where this block is stored | ||
block: A dict of block data | ||
""" | ||
request = getRequest() | ||
visitors = subscribers((context, request), IBlockVisitor) | ||
for visitor in visitors: | ||
for subblock in visitor(block): | ||
yield subblock | ||
|
||
|
||
def iter_block_transform_handlers(context, block_value, interface): | ||
"""Find valid handlers for a particular block transformation. | ||
Looks for adapters of the context and request to this interface. | ||
Then skips any that are disabled or don't match the block type, | ||
and returns the remaining handlers sorted by `order`. | ||
""" | ||
block_type = block_value.get("@type", "") | ||
handlers = [] | ||
for handler in subscribers((context, getRequest()), interface): | ||
if handler.block_type == block_type or handler.block_type is None: | ||
handler.blockid = id | ||
handlers.append(handler) | ||
for handler in sorted(handlers, key=lambda h: h.order): | ||
if not getattr(handler, "disabled", False): | ||
yield handler | ||
|
||
|
||
@implementer(IBlockVisitor) | ||
@adapter(Interface, IBrowserRequest) | ||
class NestedBlocksVisitor: | ||
"""Visit nested blocks.""" | ||
|
||
def __init__(self, context, request): | ||
pass | ||
|
||
def __call__(self, block_value): | ||
"""Visit nested blocks in ["data"]["blocks"] or ["blocks"]""" | ||
if "data" in block_value: | ||
if isinstance(block_value["data"], dict): | ||
if "blocks" in block_value["data"]: | ||
yield from block_value["data"]["blocks"].values() | ||
if "blocks" in block_value: | ||
yield from block_value["blocks"].values() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.