From 87d3f8c3223c998584fd81fe590d715bb27ff775 Mon Sep 17 00:00:00 2001 From: Alec Mitchell Date: Sun, 31 Jan 2021 10:20:43 -0800 Subject: [PATCH] Add a StaticCatalogVocabularyFactory that allows creating simple vocabularies with preset queries to use with SelectWidget, AJAXSelectWidget, etc. --- plone/app/vocabularies/catalog.py | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/plone/app/vocabularies/catalog.py b/plone/app/vocabularies/catalog.py index e279c5b..7adbca9 100644 --- a/plone/app/vocabularies/catalog.py +++ b/plone/app/vocabularies/catalog.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +import json from BTrees.IIBTree import intersection from plone.app.layout.navigation.root import getNavigationRootObject from plone.app.vocabularies import SlicableVocabulary @@ -7,6 +8,7 @@ from plone.app.vocabularies.terms import safe_simplevocabulary_from_values from plone.app.vocabularies.utils import parseQueryString from plone.memoize.instance import memoize +from plone.memoize import request from plone.registry.interfaces import IRegistry from plone.uuid.interfaces import IUUID from Products.CMFCore.utils import getToolByName @@ -23,6 +25,12 @@ from zope.schema.vocabulary import SimpleVocabulary from zope.component.hooks import getSite +try: + from zope.globalrequest import getRequest +except ImportError: + def getRequest(): + return None + import itertools import os import six @@ -588,6 +596,21 @@ def __getitem__(self, index): else: return self.createTerm(self.brains[index], None) + def getTerm(self, value): + if not isinstance(value, six.string_types): + # here we have a content and fetch the uuid as hex value + value = IUUID(value) + query = {'UID': value} + brains = self.catalog(**query) + for b in brains: + return SimpleTerm( + title=u'{} ({})'.format(b.Title, b.getPath()), + token=b.UID, + value=b.UID, + ) + + getTermByToken = getTerm + @implementer(IVocabularyFactory) class CatalogVocabularyFactory(object): @@ -646,6 +669,51 @@ def __call__(self, context, query=None): return CatalogVocabulary.fromItems(parsed, context) +def request_query_cache_key(func, vocab): + return json.dumps((vocab.query, vocab.default_text_search_index)) + + +class StaticCatalogVocabulary(CatalogVocabulary): + """Catalog Vocabulary for static lists of content based on a fixed query. + """ + + def __init__(self, query, default_text_search_index='SearchableText'): + self.query = query + self.default_text_search_index = default_text_search_index + + @staticmethod + def get_request(): + return getRequest() + + @property + @request.cache(get_key=request_query_cache_key, get_request='self.get_request()') + def brains(self): + return self.catalog(**self.query) + + @classmethod + def createTerm(cls, brain, context): + return SimpleTerm( + value=brain.UID, token=brain.UID, + title='{} ({})'.format(brain.Title, brain.getPath()) + ) + + def search(self, query): + """Required by plone.app.content.browser.vocabulary for simple queryable + vocabs, e.g. for AJAXSelectWidget.""" + if not query.endswith(' '): + query += '*' + query = {self.default_text_search_index: query} + query.update(self.query) + brains = self.catalog(**query) + return SimpleVocabulary([ + SimpleTerm( + title=u'{} ({})'.format(b.Title, b.getPath()), + token=b.UID, + value=b.UID, + ) for b in brains + ]) + + @implementer(ISource) class CatalogSource(object): """Catalog source for use with Choice fields.