Commit a6ec9f69 authored by Julien Muchembled's avatar Julien Muchembled

When deleting a object, ignore related deleted objects, including their children

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@34712 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 890e5191
...@@ -70,25 +70,6 @@ error = portal.portal_selections.selectionHasChanged(md5_object_uid_list,\n ...@@ -70,25 +70,6 @@ error = portal.portal_selections.selectionHasChanged(md5_object_uid_list,\n
\n \n
REQUEST=context.REQUEST\n REQUEST=context.REQUEST\n
qs = \'\'\n qs = \'\'\n
ret_url = \'\'\n
\n
getRelatedPropertyList = portal.portal_categories.getRelatedPropertyList\n
def Object_hasRelation(obj):\n
# Check if there is some related objets.\n
result = 0\n
for o in obj.getIndexableChildValueList():\n
for related_url in getRelatedPropertyList(o, property_name=\'relative_url\'):\n
if related_url.startswith(obj.getRelativeUrl()):\n
continue\n
elif related_url.startswith(\'portal_simulation\'):\n
continue\n
elif related_url.startswith(\'portal_trash\'):\n
continue\n
else:\n
result = 1\n
break\n
return result\n
\n
ret_url = context.absolute_url() + \'/\' + form_id\n ret_url = context.absolute_url() + \'/\' + form_id\n
if error:\n if error:\n
message = Base_translateString("Sorry, your selection has changed.")\n message = Base_translateString("Sorry, your selection has changed.")\n
...@@ -98,7 +79,7 @@ elif uids is not None:\n ...@@ -98,7 +79,7 @@ elif uids is not None:\n
object_used = 0\n object_used = 0\n
\n \n
object_list = [x.getObject() for x in context.Folder_getDeleteObjectList(uid=uids)]\n object_list = [x.getObject() for x in context.Folder_getDeleteObjectList(uid=uids)]\n
object_used = sum([Object_hasRelation(x) for x in object_list])\n object_used = sum([x.getRelationCountForDeletion() and 1 for x in object_list])\n
\n \n
if object_used > 0:\n if object_used > 0:\n
if object_used == 1:\n if object_used == 1:\n
...@@ -253,8 +234,6 @@ return REQUEST.RESPONSE.redirect("%s%s" % (ret_url, qs))\n ...@@ -253,8 +234,6 @@ return REQUEST.RESPONSE.redirect("%s%s" % (ret_url, qs))\n
<string>REQUEST</string> <string>REQUEST</string>
<string>qs</string> <string>qs</string>
<string>ret_url</string> <string>ret_url</string>
<string>getRelatedPropertyList</string>
<string>Object_hasRelation</string>
<string>message</string> <string>message</string>
<string>None</string> <string>None</string>
<string>object_used</string> <string>object_used</string>
......
...@@ -257,18 +257,15 @@ ...@@ -257,18 +257,15 @@
<record id="2" aka="AAAAAAAAAAI="> <record id="2" aka="AAAAAAAAAAI=">
<pickle> <pickle>
<tuple> <tuple>
<tuple> <global name="TALESMethod" module="Products.Formulator.TALESField"/>
<string>Products.Formulator.TALESField</string> <tuple/>
<string>TALESMethod</string>
</tuple>
<none/>
</tuple> </tuple>
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <key> <string>_text</string> </key>
<value> <string>python: len(here.portal_categories.getRelatedValueList(cell))</string> </value> <value> <string>cell/getRelationCountForDeletion</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
1567 1568
\ No newline at end of file \ No newline at end of file
...@@ -430,28 +430,37 @@ class TestERP5Core(ERP5TypeTestCase, ZopeTestCase.Functional): ...@@ -430,28 +430,37 @@ class TestERP5Core(ERP5TypeTestCase, ZopeTestCase.Functional):
def test_Folder_delete_related_object(self): def test_Folder_delete_related_object(self):
# deletion is refused if there are related objects # deletion is refused if there are related objects
module = self.portal.newContent(portal_type='Folder', id='test_folder') organisation_module_len = len(self.portal.organisation_module)
document_1 = module.newContent(portal_type='Folder', id='1') person_module_len = len(self.portal.person_module)
document_2 = module.newContent(portal_type='Folder', id='2') organisation = self.portal.organisation_module.newContent()
self.portal.portal_categories.setCategoryMembership( person = self.portal.person_module.newContent(
context=document_1, default_career_subordination_value=organisation)
base_category_list=('source',), for obj in person, organisation:
category_list=document_2.getRelativeUrl()) obj.manage_addLocalRoles(self.manager_username, ['Assignor'])
uid_list = [document_1.getUid(), document_2.getUid()]
self.portal.portal_selections.setSelectionParamsFor(
'test_selection', dict(uids=uid_list))
transaction.commit() transaction.commit()
self.assertEqual(0, organisation.getRelationCountForDeletion())
self.tic() self.tic()
self.assertEquals([document_1], self.assertEqual(2, organisation.getRelationCountForDeletion())
self.portal.portal_categories.getRelatedValueList(document_2)) self.assertEqual(0, person.getRelationCountForDeletion())
md5_string = md5.new(str(sorted([str(x) for x in uid_list]))).hexdigest() def delete(assert_deleted, obj):
redirect = module.Folder_delete(selection_name='test_selection', uid_list = [obj.getUid()]
uids=uid_list, self.portal.portal_selections.setSelectionParamsFor(
md5_object_uid_list=md5_string) 'test_selection', dict(uids=uid_list))
self.assert_('Sorry, 1 item is in use.' in redirect, redirect) md5_string = md5.new(str(sorted(str(x) for x in uid_list))).hexdigest()
transaction.savepoint(optimistic=True) redirect = obj.getParentValue().Folder_delete(uids=uid_list,
self.assertEquals(len(module.objectValues()), 2) selection_name='test_selection', md5_object_uid_list=md5_string)
self.assertTrue(('Sorry, 1 item is in use.', 'Deleted.')[assert_deleted]
in redirect, redirect)
transaction.commit()
self.tic()
delete(0, organisation)
delete(1, person)
self.assertEqual(0, organisation.getRelationCountForDeletion())
delete(1, organisation)
self.assertEquals(organisation_module_len + 1,
len(self.portal.organisation_module))
self.assertEquals(person_module_len + 1,
len(self.portal.person_module))
def test_Folder_delete_non_accessible_object(self): def test_Folder_delete_non_accessible_object(self):
# deletion is refused if there are related objects, even if those related # deletion is refused if there are related objects, even if those related
......
...@@ -2817,6 +2817,45 @@ class Base( CopyContainer, ...@@ -2817,6 +2817,45 @@ class Base( CopyContainer,
else: else:
return False return False
security.declareProtected(Permissions.AccessContentsInformation,
'isDeleted')
def isDeleted(self):
"""Test if the context is in 'deleted' state"""
for wf in self.getPortalObject().portal_workflow.getWorkflowsFor(self):
state = wf._getWorkflowStateOf(self)
if state is not None and state.getId() == 'deleted':
return True
return False
security.declareProtected(Permissions.AccessContentsInformation,
'getRelationCountForDeletion')
def getRelationCountForDeletion(self):
"""Count number of related objects preventing deletion"""
portal = self.getPortalObject()
getRelatedValueList = portal.portal_categories.getRelatedValueList
ignore_list = [x.getPhysicalPath() for x in (
portal.portal_simulation,
portal.portal_trash,
self)]
related_list = [(related.getPhysicalPath(), related)
for o in self.getIndexableChildValueList()
for related in getRelatedValueList(o)]
related_list.sort()
ignored = None
related_count = 0
for related_path, related in related_list:
if ignored is None or related_path[:len(ignored)] != ignored:
for ignored in ignore_list:
if related_path[:len(ignored)] == ignored:
break
else:
if related.isDeleted():
ignored = related_path
else:
ignored = None
related_count += 1
return related_count
# Workflow Related Method # Workflow Related Method
security.declarePublic('getWorkflowStateItemList') security.declarePublic('getWorkflowStateItemList')
def getWorkflowStateItemList(self): def getWorkflowStateItemList(self):
......
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