Commit 6a3d627a authored by Nicolas Delaby's avatar Nicolas Delaby

Avoid implicit acquisition which access base_category twice if

stored category value are like 'region/region/west'.
This can be worse when base_category id is 'resource', because 'resource'
is also a namespace adapter in z2.12. So TraversalableHandler returns a non expected object and 
keep objects to be correctly indexed.



git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@45575 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 781d6ae6
......@@ -222,6 +222,9 @@ class CategoryTool( UniqueObject, Folder, Base ):
relative_url = str(relative_url)
if base_category is not None:
relative_url = '%s/%s' % (base_category, relative_url)
relative_url = \
self._removeDuplicateBaseCategoryIdInCategoryPath(base_category,
relative_url)
node = self.unrestrictedTraverse(relative_url)
value = node
except (TypeError, KeyError, NotFound):
......@@ -567,6 +570,7 @@ class CategoryTool( UniqueObject, Folder, Base ):
else:
category = my_category.getRelativeUrl()
if my_base_category == category:
path = self._removeDuplicateBaseCategoryIdInCategoryPath(my_base_category, path)
if spec_len == 0:
if base:
membership.append(path)
......@@ -825,6 +829,7 @@ class CategoryTool( UniqueObject, Folder, Base ):
for category_url in self._getCategoryList(context):
my_base_category = category_url.split('/', 1)[0]
if my_base_category == base_category:
category_url = self._removeDuplicateBaseCategoryIdInCategoryPath(my_base_category, category_url)
#LOG("getSingleCategoryMembershipList",0,"%s %s %s %s" % (context.getRelativeUrl(),
# my_base_category, base_category, category_url))
if (checked_permission is None) or \
......@@ -1739,6 +1744,24 @@ class CategoryTool( UniqueObject, Folder, Base ):
getProperty = Base.getProperty
hasProperty = Base.hasProperty
def _removeDuplicateBaseCategoryIdInCategoryPath(self, base_category_id,
path):
"""Specific Handling to remove duplicated base_categories in path
values like in following example: 'region/region/europe/west'.
If duplicated id is a real subobject of base_category,
then the path its keept as it is
"""
splitted_path = path.split('/', 2)
if len(splitted_path) >= 2 and base_category_id == splitted_path[1]:
# It needs to be checked.
base_category_value = self._getOb(base_category_id)
if base_category_value._getOb(splitted_path[1], None) is None:
# Duplicate found, strip len(base_category_id + '/') in path
path = path[len(base_category_id)+1:]
return path
InitializeClass( CategoryTool )
# Psyco
......
......@@ -33,6 +33,8 @@ from Testing.ZopeTestCase.PortalTestCase import PortalTestCase
from AccessControl.SecurityManagement import newSecurityManager
from AccessControl.SecurityManagement import noSecurityManager
import transaction
try:
from transaction import get as get_transaction
except ImportError:
......@@ -88,7 +90,7 @@ class TestCMFCategory(ERP5TypeTestCase):
# we also enable 'destination' category on organisations
self._organisation_categories = organisation_ti.getTypeBaseCategoryList()
organisation_ti._setTypeBaseCategoryList(self._organisation_categories
+ ['destination'])
+ ['destination', 'resource'])
# Make persons.
person_module = self.getPersonModule()
......@@ -151,11 +153,18 @@ class TestCMFCategory(ERP5TypeTestCase):
portal_categories[bc].setAcquisitionCopyValue(0)
portal_categories[bc].setAcquisitionAppendValue(0)
portal_categories[bc].setFallbackBaseCategoryList(['subordination'])
for bc in ('resource', ):
if not hasattr(portal_categories, bc):
portal_categories.newContent(portal_type='Base Category',id=bc)
portal_categories[bc].setAcquisitionPortalTypeList("python: []")
portal_categories[bc].setAcquisitionMaskValue(0)
portal_categories[bc].setAcquisitionCopyValue(0)
portal_categories[bc].setAcquisitionAppendValue(0)
def beforeTearDown(self):
"""Clean up."""
# categories
for bc in ('region', 'subordination', 'gender'):
for bc in ('region', 'subordination', 'gender', 'resource'):
bc_obj = self.getPortal().portal_categories[bc]
bc_obj.manage_delObjects()
# type informations
......@@ -1010,6 +1019,67 @@ class TestCMFCategory(ERP5TypeTestCase):
self.assertNotEquals([], list(category_tool.objectIds()))
self.assertNotEquals([], list(category_tool.searchFolder()))
def test_duplicate_base_category_id_in_categories_list_properties(self):
"""check that stored values like 'region/region/west' on categories property
are cleaned up by Getters to avoid accessing base_category through
implicit Acquisition.
If region is a sub Category of Base Category region,
Relative Url must not be stripped
"""
portal_categories = self.getCategoriesTool()
organisation = self.getOrganisationModule().newContent(
portal_type='Organisation',
region='region/europe/west')
person = self.getPersonModule().newContent(portal_type='Person',
default_career_subordination_value=organisation)
self.assertTrue(organisation.hasRegion())
self.assertEquals(organisation.getRegion(), 'europe/west')
self.assertEquals(organisation.getRegionList(), ['europe/west'])
old_west_region = organisation.getRegionValue()
self.assertEquals(old_west_region.getPortalType(), 'Category')
# Check acquired categories
self.assertEquals(person.getRegion(), 'europe/west')
self.assertEquals(person.getRegionList(), ['europe/west'])
region_base_category = portal_categories.region
new_region = region_base_category.newContent(portal_type='Category',
id='region')
new_region = new_region.newContent(portal_type='Category', id='europe')
new_region = new_region.newContent(portal_type='Category', id='west')
self.assertEquals(organisation.getRegion(), 'region/europe/west')
self.assertEquals(organisation.getRegionList(), ['region/europe/west'])
self.assertEquals(organisation.getRegionValue().getPortalType(), 'Category')
self.assertNotEquals(organisation.getRegionValue(), old_west_region)
self.assertEquals(person.getRegion(), 'region/europe/west')
self.assertEquals(person.getRegionList(), ['region/europe/west'])
# Let's continue with resource because its ID conflict with
# "traversing namespaces" names
resource_value = portal_categories.resource.newContent(portal_type='Category', id='id1')
organisation.setResource('resource/id1')
self.assertEquals(organisation.getResource(), 'id1')
self.assertEquals(organisation.getResourceValue(), resource_value)
self.assertEquals(organisation.getResourceList(), ['id1'])
self.assertEquals(organisation.getResourceValue(portal_type='Category'),
resource_value)
self.assertEquals(organisation.getResourceValueList(portal_type='Category'),
[resource_value])
# Check other public methods of CategoryTool
self.assertEquals(portal_categories.getCategoryMembershipList(organisation,
'resource', portal_type='Category'),
['id1'])
self.assertEquals(portal_categories.getSingleCategoryMembershipList(
organisation, 'resource',
portal_type='Category'),
['id1'])
# Check indexation
transaction.commit()
self.tic()
def test_suite():
suite = unittest.TestSuite()
......
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