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

Add endpoint that uses plone.volto block_types indexer (wip) #1789

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Empty file.
15 changes: 15 additions & 0 deletions src/plone/restapi/services/blocktypes/configure.zcml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:plone="http://namespaces.plone.org/plone"
xmlns:zcml="http://namespaces.zope.org/zcml"
>

<plone:service
method="GET"
factory=".get.BlockTypesGet"
for="zope.interface.Interface"
permission="zope2.View"
name="@blocktypes"
/>

</configure>
39 changes: 39 additions & 0 deletions src/plone/restapi/services/blocktypes/get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from plone import api
from plone.restapi.services import Service
from collections import Counter
from plone.dexterity.content import get_assignable


class BlockTypesGet(Service):
def reply(self):
catalog = api.portal.get_tool(name="portal_catalog")
request_body = self.request.form
result = {}

if request_body.get("blocktypes") != "":
blocktypes = request_body.get("blocktypes").split(",")

for blocktype in blocktypes:
brains = catalog.searchResults(block_types=blocktype)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am sure this can be optimized to one query with removal of the for loop.

result[blocktype] = Counter()

for brain in brains:
obj = brain.getObject()
Copy link
Member

@jensens jensens May 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above query could ask the object_provides index for the (marker) interface of the volto.blocks behavior. This would save several an object wake ups.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried the object_provides index for the marker interface of the volto.blocks behavior like so: brains = catalog(object_provides=IBlocks.__identifier__) which returns brains just like the block_types index. And so I am asking my self: Doesn't this make the block_types index completely unnecessary? Because from the brains I get the object and from there I get the block values.

/cc @davisagli

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonaspiterek You can do that but then you end up loading the full object for all the content items that have blocks, and loading the full object is slower than loading the metadata that is stored as part of the catalog. The block_types index exists for the use case where you want to find all the items that have a particular type of block, without actually loading the full objects.

Also the block_types index properly finds blocks that are nested inside other blocks, which your code doesn't do yet.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonaspiterek Btw if you just want to find out how many items have each type of block, you can also get that efficiently from the index like this (if I recall correctly): api.portal.get_tool("portal_catalog").Indexes["block_types"].uniqueValues(withLengths=1)

assignable = get_assignable(obj)

hasBlocksBehavior = bool(
{
behavior
for behavior in assignable.enumerateBehaviors()
if behavior.name == "volto.blocks"
}
)

if hasBlocksBehavior:
url = brain.getURL() # or brain.getPath()

for block in obj.blocks.values():
if block["@type"] == blocktype:
result[blocktype].update({url: 1})

return result
1 change: 1 addition & 0 deletions src/plone/restapi/services/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<include package=".actions" />
<include package=".addons" />
<include package=".aliases" />
<include package=".blocktypes" />
<include package=".breadcrumbs" />
<include package=".content" />
<include package=".controlpanels" />
Expand Down
Loading