Commit 9b5fbc18 authored by Kazuhiko Shiozaki's avatar Kazuhiko Shiozaki Committed by Kazuhiko Shiozaki

Predicate: support NULL membership criteria.

parent a4a3b7bf
......@@ -65,6 +65,12 @@ class TestPredicateMixIn(ERP5TypeTestCase):
self.createCategories()
self.login()
def beforeTearDown(self):
self.portal.organisation_module.manage_delObjects(
ids=list(self.portal.organisation_module.objectIds())
)
self.tic()
def playSequence(self, sequence_string, quiet=QUIET) :
# don't commit between steps
sequence = Sequence()
......@@ -323,6 +329,22 @@ class TestPredicates(TestPredicateMixIn):
['region/europe/western_europe/germany'])
self.assertFalse(pred.test(doc))
def test_BasicCategoryNullMembership(self):
# if the document is any member of the base category, the predicate returns
# false
doc1 = self.createDocument()
doc2 = self.createDocument(region='europe/western_europe/france',)
self.tic()
pred = self.createPredicate(
membership_criterion_base_category_list=['region'],
membership_criterion_category_list=['region/NULL'])
self.assertTrue(pred.test(doc1))
self.assertFalse(pred.test(doc2))
self.assertItemsEqual(
[doc1],
[x.getObject() for x in pred.searchResults(portal_type='Organisation')]
)
def test_NonExistantCategoryMembership(self):
# the predicate also return false for non existant category and no error is
# raised.
......
......@@ -1210,7 +1210,7 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
for base_category_id, document_set in base_category_dict.iteritems():
column = prefix + base_category_id + suffix
category_query = SimpleQuery(**{
column: {document.getUid() for document in document_set},
column: {None if document is None else document.getUid() for document in document_set},
})
extra_query = onJoin(column)
if extra_query is not None:
......
......@@ -161,14 +161,17 @@ class Predicate(XMLObject):
isMemberOf = context._getCategoryTool().isMemberOf
with readOnlyTransactionCache():
for c in membership_criterion_category_list:
bc = c.split('/', 1)[0]
bc, c_path = c.split('/', 1)
is_null = c_path == 'NULL'
if tested_base_category_list is None or bc in tested_base_category_list:
if bc in multimembership_criterion_base_category_list:
if not isMemberOf(context, c, strict_membership=strict_membership):
if (is_null and isMemberOf(context, bc, strict_membership=False)) or \
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] = \
(is_null and not isMemberOf(context, bc, strict_membership=False)) or \
isMemberOf(context, c, strict_membership=strict_membership)
if 0 in tested_base_category.itervalues():
return 0
......@@ -250,7 +253,7 @@ class Predicate(XMLObject):
getCategoryParameterDict(
filterCategoryList(getBaseCategorySet(), getCategoryList()),
strict_membership=strict_membership,
onMissing=lambda category: False,
onMissing=lambda category: category.split('/', 1)[1] == 'NULL',
),
)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment