diff --git a/product/CMFActivity/ActivityTool.py b/product/CMFActivity/ActivityTool.py index d005395e5f68594c63f023a3f07f4a464fbea241..7cd0a3648e00eb813612d8dba976afa4aa18c3fc 100644 --- a/product/CMFActivity/ActivityTool.py +++ b/product/CMFActivity/ActivityTool.py @@ -134,7 +134,13 @@ class Message: self.traceback = None self.processing = None self.user_name = str(_getAuthenticatedUser(self)) - # Store REQUEST Info ? + # Store REQUEST Info + request = getattr(obj, 'REQUEST', None) + if request is not None: + self.request_info = dict( + SERVER_URL=request.other['SERVER_URL'], + VirtualRootPhysicalPath=request.other.get('VirtualRootPhysicalPath'), + _script=list(request._script)) def getObject(self, activity_tool): """return the object referenced in this message.""" @@ -805,7 +811,18 @@ class ActivityTool (Folder, UniqueObject): if parents is None: warn('CMFActivity.ActivityTool.invoke: PARENTS is not defined in REQUEST. It should only happen in unit tests.') request['PARENTS'] = self.aq_chain[:] - new_request_container = request_container.__class__(REQUEST=request.clone()) + + # restore request information + new_request = request.clone() + request_info = getattr(message, 'request_info', None) + if request_info is not None: + new_request.other['SERVER_URL'] = request_info['SERVER_URL'] + virtual_root_path = request_info.get('VirtualRootPhysicalPath') + if virtual_root_path: + new_request.other['VirtualRootPhysicalPath'] = virtual_root_path + new_request._script = request_info['_script'] + + new_request_container = request_container.__class__(REQUEST=new_request) # Recreate acquisition chain. my_self = new_request_container base_chain.reverse() diff --git a/product/CMFActivity/tests/testCMFActivity.py b/product/CMFActivity/tests/testCMFActivity.py index 150a5be08733a534844adfdccb484c06749c39a2..d0b9bd10613b378ae88c68c6c8a0bbc104a2aacd 100644 --- a/product/CMFActivity/tests/testCMFActivity.py +++ b/product/CMFActivity/tests/testCMFActivity.py @@ -2798,6 +2798,45 @@ class TestCMFActivity(ERP5TypeTestCase): LOG('Testing... ',0,message) self.CheckSerializationTag('SQLQueue') + def test_108_testAbsoluteUrl(self): + # Tests that absolute_url works in activities. The URL generation is based + # on REQUEST information when the method was activated. + request = self.portal.REQUEST + + request.setServerURL('http', 'test.erp5.org', '9080') + request.other['PARENTS'] = [self.portal.organisation_module] + request.setVirtualRoot('virtual_root') + + calls = [] + def checkAbsoluteUrl(self): + calls.append(self.absolute_url()) + Organisation.checkAbsoluteUrl = checkAbsoluteUrl + + try: + o = self.portal.organisation_module.newContent( + portal_type='Organisation', id='test_obj') + self.assertEquals(o.absolute_url(), + 'http://test.erp5.org:9080/virtual_root/test_obj') + o.activate().checkAbsoluteUrl() + + # Reset server URL and virtual root before executing messages. + # This simulates the case of activities beeing executed with different + # REQUEST, such as TimerServer. + request.setServerURL('https', 'anotherhost.erp5.org', '443') + request.other['PARENTS'] = [self.app] + request.setVirtualRoot('') + # obviously, the object url is different + self.assertEquals(o.absolute_url(), + 'https://anotherhost.erp5.org/%s/organisation_module/test_obj' + % self.portal.getId()) + + # but activities are executed using the previous request information + self.flushAllActivities(loop_size=1000) + self.assertEquals(calls, ['http://test.erp5.org:9080/virtual_root/test_obj']) + finally: + delattr(Organisation, 'checkAbsoluteUrl') + + def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestCMFActivity))