diff --git a/product/ERP5/Tool/DomainTool.py b/product/ERP5/Tool/DomainTool.py index 7424aca2cac9335e00ab534830a282a754978d53..90caae84c13271acec68a01ee826aa2789f71487 100644 --- a/product/ERP5/Tool/DomainTool.py +++ b/product/ERP5/Tool/DomainTool.py @@ -242,18 +242,26 @@ class DomainTool(BaseTool): if kw.get('src__'): return sql_result_list result_list = [] - for predicate in sql_result_list: - predicate = predicate.getObject() - if (not test) or predicate.test( - context, - tested_base_category_list=tested_base_category_list): - result_list.append(predicate) - if filter_method is not None: - result_list = filter_method(result_list) - if sort_key_method is not None: - result_list.sort(key=sort_key_method) - elif sort_method is not None: - result_list.sort(cmp=sort_method) + if sql_result_list: + if test: + cache = {} + def isMemberOf(context, c, strict_membership): + if c in cache: + return cache[c] + cache[c] = result = portal_categories.isMemberOf( + context, c, strict_membership=strict_membership) + return result + for predicate in sql_result_list: + predicate = predicate.getObject() + if not test or predicate.test(context, tested_base_category_list, + isMemberOf=isMemberOf): + result_list.append(predicate) + if filter_method is not None: + result_list = filter_method(result_list) + if sort_key_method is not None: + result_list.sort(key=sort_key_method) + elif sort_method is not None: + result_list.sort(cmp=sort_method) return result_list # XXX FIXME method should not be public diff --git a/product/ERP5Type/Core/Predicate.py b/product/ERP5Type/Core/Predicate.py index 838b6fde4997b11c515922fdaabc7ef347f64fb9..4a111472f943fff7068a5e51ef478ba9c28bee43 100644 --- a/product/ERP5Type/Core/Predicate.py +++ b/product/ERP5Type/Core/Predicate.py @@ -87,7 +87,7 @@ class Predicate(XMLObject): security.declareProtected( Permissions.AccessContentsInformation, 'test' ) def test(self, context, tested_base_category_list=None, - strict_membership=0, **kw): + strict_membership=0, isMemberOf=None, **kw): """ A Predicate can be tested on a given context. Parameters can passed in order to ignore some conditions. @@ -97,6 +97,9 @@ class Predicate(XMLObject): destination or the source of a predicate. - if strict_membership is specified, we should make sure that we are strictly a member of tested categories + - isMemberOf can be a function caching results for + CategoryTool.isMemberOf: it is always called with given 'context' and + 'strict_membership' values, and different categories. """ self = self.asPredicate() if self is None: @@ -150,17 +153,19 @@ class Predicate(XMLObject): # Test category memberships. Enable the read-only transaction cache # because this part is strictly read-only, and context.isMemberOf # is very expensive when the category list has many items. + if isMemberOf is None: + isMemberOf = context._getCategoryTool().isMemberOf with readOnlyTransactionCache(): for c in self.getMembershipCriterionCategoryList(): bc = c.split('/', 1)[0] if tested_base_category_list is None or bc in tested_base_category_list: if bc in multimembership_criterion_base_category_list: - if not context.isMemberOf(c, strict_membership=strict_membership): + if not isMemberOf(context, c, strict_membership=strict_membership): return 0 elif bc in membership_criterion_base_category_list and \ not tested_base_category.get(bc): tested_base_category[bc] = \ - context.isMemberOf(c, strict_membership=strict_membership) + isMemberOf(context, c, strict_membership=strict_membership) if 0 in tested_base_category.itervalues(): return 0