IContextSourceBinder and validation in Plone 5.2

We use IContextSourceBinder frequently e.g.

    form.widget("gl_refs_my_onkopedia", SelectWidget, multiple="multiple")
    gl_refs_my_onkopedia = schema.List(
        title=_("References to My-Onkopedia"),
        description=_("References to My-Onkopedia"),
        required=False,
        value_type=schema.Choice(
            source=OnkopediaPathBinder(["my-onkopedia", "mein-onkopedia"])
        ),
        default=[],
    )

with

@implementer(IContextSourceBinder)
class OnkopediaPathBinder(object):
    """ Returns all linkable objects in a given subarea of Onkopedia"""

    def __init__(self, areas, subpath="guidelines", drug_assessment=False):
        super(OnkopediaPathBinder, self).__init__()
        assert isinstance(areas, (list, tuple)), "areas must be tuple or list"
        self.areas = areas
        self.subpath = subpath
        self.drug_assessment = drug_assessment

    def __call__(self, context):

        items = list()
        portal = plone.api.portal.get()

        uuids_seen = set()
        for area in self.areas:
            language = (
                "de" if "/onkopedia/de" in "/".join(context.getPhysicalPath()) else "en"
            )
            path = "{}/{}".format(language, area)
            if self.subpath:
                path += "/{}".format(self.subpath)
            target_folder = portal.restrictedTraverse(path, None)
            if target_folder is not None:
                for brain in target_folder.getFolderContents():

                    if brain.UID in uuids_seen:
                        continue

                    if self.drug_assessment:
                        title = safe_unicode(brain.Title)
                        title += " (" + safe_unicode(brain.topic_str)
                        if brain.specifications_str:
                            title += ", {}".format(
                                safe_unicode(brain.specifications_str)
                            )
                        if brain.specifications2_str:
                            title += ", {}".format(
                                safe_unicode(brain.specifications2_str)
                            )
                        title += ")"
                        items.append(SimpleTerm(brain.UID, brain.UID, title))
                    else:
                        items.append(SimpleTerm(brain.UID, brain.UID, brain.Title))
                    uuids_seen.add(brain.UID)

        items = sorted(items, key=operator.attrgetter("title"))
        return VocabularyWrapper(SimpleVocabulary(items))


class VocabularyWrapper(object):
    """ Wraps a SimpleVocabulary into a searchable source """

    def __init__(self, vocabulary):
        self.vocabulary = vocabulary

    def getTermByToken(self, token):
        return self.vocabulary.getTermByToken(token)

    def __contains__(self, name):
        return name in self.vocabulary

    def getTerm(self, term):
        return self.vocabulary.getTerm(term)

    def __iter__(self):
        for item in self.vocabulary:
            yield item

    def search(self, query_string):
        items = []
        for term in self.vocabulary:
            if query_string.lower() in term.title.lower():
                items.append(term)
        return items
~
1 Like