Commit 7667ca94 authored by Jérome Perrin's avatar Jérome Perrin

Support new arguments to getCategoryChild*List to easily sort items of the same

level. Look at the test for more info



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@14618 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 242a19b0
...@@ -215,40 +215,63 @@ class Category(Folder): ...@@ -215,40 +215,63 @@ class Category(Folder):
'getCategoryChildValueList') 'getCategoryChildValueList')
def getCategoryChildValueList(self, recursive=1, include_if_child=1, def getCategoryChildValueList(self, recursive=1, include_if_child=1,
is_self_excluded=1, sort_on=None, is_self_excluded=1, sort_on=None,
sort_order=None, **kw): sort_order=None, local_sort_method=None,
local_sort_id=None, **kw):
""" """
List the child objects of this category and all its subcategories. List the child objects of this category and all its subcategories.
recursive - if set to 1, list recursively recursive - if set to 1, list recursively
include_if_child - if set to 1, categories having child categories include_if_child - if set to 1, categories having child categories
are not included are not included
is_self_excluded - if set to 1, exclude this category from the list is_self_excluded - if set to 1, exclude this category from the list
sort_on, sort_order - the same semantics as ZSQLCatalog sort_on, sort_order - the same semantics as ZSQLCatalog
sort_on specifies properties used for sorting sort_on specifies properties used for sorting
sort_order specifies how categories are sorted sort_order specifies how categories are sorted.
The default is to do a preorder tree traversal on
all sub-objects.
WARNING: using these parameters can slow down WARNING: using these parameters can slow down
significantly, because this is written in significantly, because this is written in Python
Python
local_sort_method - When using the default preorder traversal, use
this function to sort objects of the same depth.
local_sort_id - When using the default preorder traversal, sort
objects of the same depth by comparing their
'local_sort_id' property.
Renderer parameter are also supported here.
""" """
if is_self_excluded or ( if is_self_excluded or (
not(include_if_child) and not(include_if_child) and
len(self.objectValues(self.allowed_types)) > 0): len(self.objectIds(self.allowed_types)) > 0):
value_list = [] value_list = []
else: else:
value_list = [self] value_list = [self]
child_value_list = self.objectValues(self.allowed_types)
if local_sort_id:
local_sort_method = lambda a, b: cmp(a.getProperty(local_sort_id),
b.getProperty(local_sort_id))
if local_sort_method:
# sort objects at the current level
child_value_list = list(child_value_list)
child_value_list.sort(local_sort_method)
if recursive: if recursive:
for c in self.objectValues(self.allowed_types): for c in child_value_list:
# Do not pass sort parameters intentionally, because sorting # Do not global pass sort parameters intentionally, because sorting
# needs to be done only at the end of recursive calls. # needs to be done only at the end of recursive calls.
value_list.extend(c.getCategoryChildValueList(recursive=1, value_list.extend(c.getCategoryChildValueList(recursive=1,
is_self_excluded=0, is_self_excluded=0,
include_if_child=include_if_child)) include_if_child=include_if_child,
local_sort_method=local_sort_method,
local_sort_id=local_sort_id))
else: else:
for c in self.objectValues(self.allowed_types): for c in child_value_list:
value_list.append(c) value_list.append(c)
return sortValueList(value_list, sort_on, sort_order, **kw) return sortValueList(value_list, sort_on, sort_order, **kw)
...@@ -390,6 +413,9 @@ class Category(Folder): ...@@ -390,6 +413,9 @@ class Category(Folder):
display_id -- method called to build the couple display_id -- method called to build the couple
recursive -- if set to 0 do not apply recursively recursive -- if set to 0 do not apply recursively
All parameter supported by getCategoryChildValueList and Render are
supported here.
""" """
def _renderCategoryChildItemList(recursive=1, base=0, **kw): def _renderCategoryChildItemList(recursive=1, base=0, **kw):
value_list = self.getCategoryChildValueList(recursive=recursive,**kw) value_list = self.getCategoryChildValueList(recursive=recursive,**kw)
...@@ -650,7 +676,8 @@ class BaseCategory(Category): ...@@ -650,7 +676,8 @@ class BaseCategory(Category):
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getCategoryChildValueList') 'getCategoryChildValueList')
def getCategoryChildValueList(self, is_self_excluded=1, recursive=1, def getCategoryChildValueList(self, is_self_excluded=1, recursive=1,
include_if_child=1, sort_on=None, sort_order=None, **kw): include_if_child=1, sort_on=None, sort_order=None,
local_sort_method=None, local_sort_id=None, **kw):
""" """
List the child objects of this category and all its subcategories. List the child objects of this category and all its subcategories.
...@@ -667,28 +694,50 @@ class BaseCategory(Category): ...@@ -667,28 +694,50 @@ class BaseCategory(Category):
region/europe/france region/europe/france
region/europe/germany region/europe/germany
... ...
sort_on, sort_order - sort categories in 'sort_order' by comparing
the 'sort_on' attribute. The default is to do a preorder tree
traversal on all subobjects.
local_sort_method - When using the default preorder traversal, use
this function to sort objects of the same depth.
local_sort_id - When using the default preorder traversal, sort
objects of the same depth by comparing their
'local_sort_id' property.
Renderer parameter are also supported here.
""" """
if is_self_excluded: if is_self_excluded:
value_list = [] value_list = []
else: else:
value_list = [self] value_list = [self]
child_value_list = self.objectValues(self.allowed_types)
if local_sort_id:
local_sort_method = lambda a, b: cmp(a.getProperty(local_sort_id),
b.getProperty(local_sort_id))
if local_sort_method:
# sort objects at the current level
child_value_list = list(child_value_list)
child_value_list.sort(local_sort_method)
if recursive: if recursive:
for c in self.objectValues(self.allowed_types): for c in child_value_list:
value_list.extend(c.getCategoryChildValueList(recursive=1, value_list.extend(c.getCategoryChildValueList(recursive=1,
is_self_excluded=0, is_self_excluded=0,
include_if_child=include_if_child)) include_if_child=include_if_child))
else: else:
for c in self.objectValues(self.allowed_types): for c in child_value_list:
if include_if_child: if include_if_child:
value_list.append(c) value_list.append(c)
else: else:
if len(c.objectValues(self.allowed_types))==0: if len(c.objectIds(self.allowed_types))==0:
value_list.append(c) value_list.append(c)
return sortValueList(value_list, sort_on, sort_order, **kw) return sortValueList(value_list, sort_on, sort_order, **kw)
# Alias for compatibility # Alias for compatibility
security.declareProtected(Permissions.AccessContentsInformation, security.declareProtected(Permissions.AccessContentsInformation,
'getBaseCategory') 'getBaseCategory')
getBaseCategory = getBaseCategoryValue getBaseCategory = getBaseCategoryValue
......
...@@ -834,6 +834,56 @@ class TestCMFCategory(ERP5TypeTestCase): ...@@ -834,6 +834,56 @@ class TestCMFCategory(ERP5TypeTestCase):
self.assertSameSet(c1.getCategoryChildValueList(is_self_excluded=0), self.assertSameSet(c1.getCategoryChildValueList(is_self_excluded=0),
(c1, c11, c111)) (c1, c11, c111))
def test_24_getCategoryChildValueListLocalSortMethod(self,
quiet=quiet, run=run_all_test) :
if not run: return
if not quiet:
message = 'Test getCategoryChildValueList local sort method'
ZopeTestCase._print('\n '+message)
LOG('Testing... ', 0, message)
pc = self.getCategoriesTool()
bc = pc.newContent(portal_type='Base Category', id='child_test')
c1 = bc.newContent(portal_type='Category', id='1', int_index=10, title='C')
c11 = c1.newContent(portal_type='Category', id='1.1', int_index=5, title='X')
c111 = c11.newContent(portal_type='Category', id='1.1.1',
int_index=2, title='C')
c12 = c1.newContent(portal_type='Category', id='1.2', int_index=3, title='Z')
c2 = bc.newContent(portal_type='Category', id='2', int_index=30, title='B')
c3 = bc.newContent(portal_type='Category', id='3', int_index=20, title='A')
# the default ordering is preorder:
self.assertEquals(list(bc.getCategoryChildValueList()),
[c1, c11, c111, c12, c2, c3])
self.assertEquals(list(c1.getCategoryChildValueList()), [c11, c111, c12])
# but this order can be controlled for categories of the same depth, ie. we
# can sort each level independantly (this is different from sort_on /
# sort_order which sort the whole list regardless of the original
# structure).
# This can be done either with a function (like cmp argument to python
# list sort)
def sort_func(a, b):
return cmp(a.getTitle(), b.getTitle())
# here c1, c2, c3 are sorted by their titles
self.assertEquals(list(bc.getCategoryChildValueList(
local_sort_method=sort_func)),
[c3, c2, c1, c11, c111, c12])
# here c11 & c12 are sorted by their titles
self.assertEquals(list(c1.getCategoryChildValueList(
local_sort_method=sort_func)), [c11, c111, c12])
# This can also be done with a local_sort_id, then objects are sorted by
# comparing this 'sort_id' property (using getProperty())
# here c1, c2, c3 are sorted by their int_index
self.assertEquals(list(bc.getCategoryChildValueList(
local_sort_id='int_index')),
[c1, c11, c111, c12, c3, c2])
# here c11 & c12 are sorted by their titles
self.assertEquals(list(c1.getCategoryChildValueList(
local_sort_id='int_index')), [c12, c11, c111])
if __name__ == '__main__': if __name__ == '__main__':
framework() framework()
......
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