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
\n
REQUEST=context.REQUEST\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
if error:\n
message = Base_translateString("Sorry, your selection has changed.")\n
......@@ -98,7 +79,7 @@ elif uids is not None:\n
object_used = 0\n
\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
if object_used > 0:\n
if object_used == 1:\n
......@@ -253,8 +234,6 @@ return REQUEST.RESPONSE.redirect("%s%s" % (ret_url, qs))\n
<string>REQUEST</string>
<string>qs</string>
<string>ret_url</string>
<string>getRelatedPropertyList</string>
<string>Object_hasRelation</string>
<string>message</string>
<string>None</string>
<string>object_used</string>
......
......@@ -257,18 +257,15 @@
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<tuple>
<tuple>
<string>Products.Formulator.TALESField</string>
<string>TALESMethod</string>
</tuple>
<none/>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
<tuple/>
</tuple>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python: len(here.portal_categories.getRelatedValueList(cell))</string> </value>
<value> <string>cell/getRelationCountForDeletion</string> </value>
</item>
</dictionary>
</pickle>
......
1567
\ No newline at end of file
1568
\ No newline at end of file
......@@ -430,28 +430,37 @@ class TestERP5Core(ERP5TypeTestCase, ZopeTestCase.Functional):
def test_Folder_delete_related_object(self):
# deletion is refused if there are related objects
module = self.portal.newContent(portal_type='Folder', id='test_folder')
document_1 = module.newContent(portal_type='Folder', id='1')
document_2 = module.newContent(portal_type='Folder', id='2')
self.portal.portal_categories.setCategoryMembership(
context=document_1,
base_category_list=('source',),
category_list=document_2.getRelativeUrl())
uid_list = [document_1.getUid(), document_2.getUid()]
self.portal.portal_selections.setSelectionParamsFor(
'test_selection', dict(uids=uid_list))
organisation_module_len = len(self.portal.organisation_module)
person_module_len = len(self.portal.person_module)
organisation = self.portal.organisation_module.newContent()
person = self.portal.person_module.newContent(
default_career_subordination_value=organisation)
for obj in person, organisation:
obj.manage_addLocalRoles(self.manager_username, ['Assignor'])
transaction.commit()
self.assertEqual(0, organisation.getRelationCountForDeletion())
self.tic()
self.assertEquals([document_1],
self.portal.portal_categories.getRelatedValueList(document_2))
md5_string = md5.new(str(sorted([str(x) for x in uid_list]))).hexdigest()
redirect = module.Folder_delete(selection_name='test_selection',
uids=uid_list,
md5_object_uid_list=md5_string)
self.assert_('Sorry, 1 item is in use.' in redirect, redirect)
transaction.savepoint(optimistic=True)
self.assertEquals(len(module.objectValues()), 2)
self.assertEqual(2, organisation.getRelationCountForDeletion())
self.assertEqual(0, person.getRelationCountForDeletion())
def delete(assert_deleted, obj):
uid_list = [obj.getUid()]
self.portal.portal_selections.setSelectionParamsFor(
'test_selection', dict(uids=uid_list))
md5_string = md5.new(str(sorted(str(x) for x in uid_list))).hexdigest()
redirect = obj.getParentValue().Folder_delete(uids=uid_list,
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):
# deletion is refused if there are related objects, even if those related
......
......@@ -2817,6 +2817,45 @@ class Base( CopyContainer,
else:
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
security.declarePublic('getWorkflowStateItemList')
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