diff --git a/bt5/erp5_upgrader/SkinTemplateItem/portal_skins/erp5_upgrader/Base_getConstraintTypeListPerPortalType.py b/bt5/erp5_upgrader/SkinTemplateItem/portal_skins/erp5_upgrader/Base_getConstraintTypeListPerPortalType.py index e803cc007b353e0ed5fd1f7d3fbf0e47e58f6a95..6ee69053cacb10dac3d3d93d742e5b108cdb4936 100644 --- a/bt5/erp5_upgrader/SkinTemplateItem/portal_skins/erp5_upgrader/Base_getConstraintTypeListPerPortalType.py +++ b/bt5/erp5_upgrader/SkinTemplateItem/portal_skins/erp5_upgrader/Base_getConstraintTypeListPerPortalType.py @@ -40,13 +40,12 @@ for property_sheet_id, category_list in constraint_type_per_id.iteritems(): constraint_type_per_type.setdefault(portal_type, set()).update(category_list) portal_type_tool = portal.portal_types -portal_type_list = constraint_type_per_type.keys() -for portal_type in portal_type_list: +for portal_type in list(constraint_type_per_type.keys()): allowed_content_type_list = \ portal_type_tool[portal_type].getTypeAllowedContentTypeList() for allowed_content_type in allowed_content_type_list: - if allowed_content_type in portal_type_list: + if allowed_content_type in constraint_type_per_type: type_list = constraint_type_per_type.pop(allowed_content_type) for constraint_type in type_list: type_per_constraint_type[constraint_type].remove(allowed_content_type) diff --git a/bt5/erp5_web/PortalTypePropertySheetTemplateItem/property_sheet_list.xml b/bt5/erp5_web/PortalTypePropertySheetTemplateItem/property_sheet_list.xml index 0e5713010d2b4e292a28b1d20f0f91e2e2eb85c4..85f1c06f36c888f5e34d7f6c19578aa84d0064a7 100644 --- a/bt5/erp5_web/PortalTypePropertySheetTemplateItem/property_sheet_list.xml +++ b/bt5/erp5_web/PortalTypePropertySheetTemplateItem/property_sheet_list.xml @@ -1,8 +1,10 @@ <property_sheet_list> <portal_type id="Static Web Section"> <item>SortIndex</item> + <item>WebSectionUpgradeConstraint</item> </portal_type> <portal_type id="Static Web Site"> + <item>WebSectionUpgradeConstraint</item> <item>WebSitePreference</item> </portal_type> <portal_type id="Web Page"> @@ -11,8 +13,10 @@ </portal_type> <portal_type id="Web Section"> <item>SortIndex</item> + <item>WebSectionUpgradeConstraint</item> </portal_type> <portal_type id="Web Site"> + <item>WebSectionUpgradeConstraint</item> <item>WebSitePreference</item> </portal_type> </property_sheet_list> \ No newline at end of file diff --git a/bt5/erp5_web/PropertySheetTemplateItem/portal_property_sheets/WebSectionUpgradeConstraint.xml b/bt5/erp5_web/PropertySheetTemplateItem/portal_property_sheets/WebSectionUpgradeConstraint.xml new file mode 100644 index 0000000000000000000000000000000000000000..f3bf6aa9d09986f66a9733c517010fcd1058002c --- /dev/null +++ b/bt5/erp5_web/PropertySheetTemplateItem/portal_property_sheets/WebSectionUpgradeConstraint.xml @@ -0,0 +1,66 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="Property Sheet" module="erp5.portal_type"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_count</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent> + </value> + </item> + <item> + <key> <string>_mt_index</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> + </value> + </item> + <item> + <key> <string>_tree</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent> + </value> + </item> + <item> + <key> <string>description</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>WebSectionUpgradeConstraint</string> </value> + </item> + <item> + <key> <string>portal_type</string> </key> + <value> <string>Property Sheet</string> </value> + </item> + </dictionary> + </pickle> + </record> + <record id="2" aka="AAAAAAAAAAI="> + <pickle> + <global name="Length" module="BTrees.Length"/> + </pickle> + <pickle> <int>0</int> </pickle> + </record> + <record id="3" aka="AAAAAAAAAAM="> + <pickle> + <global name="OOBTree" module="BTrees.OOBTree"/> + </pickle> + <pickle> + <none/> + </pickle> + </record> + <record id="4" aka="AAAAAAAAAAQ="> + <pickle> + <global name="OOBTree" module="BTrees.OOBTree"/> + </pickle> + <pickle> + <none/> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_web/PropertySheetTemplateItem/portal_property_sheets/WebSectionUpgradeConstraint/default_page_modification_date_constraint.xml b/bt5/erp5_web/PropertySheetTemplateItem/portal_property_sheets/WebSectionUpgradeConstraint/default_page_modification_date_constraint.xml new file mode 100644 index 0000000000000000000000000000000000000000..1aae27d7b0ba83f7793657705c4469eaaa00743b --- /dev/null +++ b/bt5/erp5_web/PropertySheetTemplateItem/portal_property_sheets/WebSectionUpgradeConstraint/default_page_modification_date_constraint.xml @@ -0,0 +1,80 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="Script Constraint" module="erp5.portal_type"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>_identity_criterion</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent> + </value> + </item> + <item> + <key> <string>_range_criterion</string> </key> + <value> + <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent> + </value> + </item> + <item> + <key> <string>categories</string> </key> + <value> + <tuple> + <string>constraint_type/post_upgrade</string> + </tuple> + </value> + </item> + <item> + <key> <string>description</string> </key> + <value> + <none/> + </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>default_page_modification_date_constraint</string> </value> + </item> + <item> + <key> <string>portal_type</string> </key> + <value> <string>Script Constraint</string> </value> + </item> + <item> + <key> <string>script_id</string> </key> + <value> <string>WebSection_checkDefaultPageModificationDateConsistency</string> </value> + </item> + </dictionary> + </pickle> + </record> + <record id="2" aka="AAAAAAAAAAI="> + <pickle> + <global name="PersistentMapping" module="Persistence.mapping"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>data</string> </key> + <value> + <dictionary/> + </value> + </item> + </dictionary> + </pickle> + </record> + <record id="3" aka="AAAAAAAAAAM="> + <pickle> + <global name="PersistentMapping" module="Persistence.mapping"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>data</string> </key> + <value> + <dictionary/> + </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web/WebSection_checkDefaultPageModificationDateConsistency.py b/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web/WebSection_checkDefaultPageModificationDateConsistency.py new file mode 100644 index 0000000000000000000000000000000000000000..7f2bcce4d4258b34b118d8450bf9e3fb1c1b1126 --- /dev/null +++ b/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web/WebSection_checkDefaultPageModificationDateConsistency.py @@ -0,0 +1,31 @@ +from Products.ERP5Type.Message import translateString +portal = context.getPortalObject() +getDocumentValue = context.getDocumentValue +error_list = [] + +# Check that the web section is more recent that the default pages. +if context.getAggregate(): + max_content_modification_date = context.getModificationDate() + for default_page_reference in context.getAggregateReferenceList(): + if default_page_reference: + for language in (None,) + context.getAvailableLanguageList(): + default_page = getDocumentValue( + default_page_reference, + language=language, + ) + if default_page is not None: + max_content_modification_date = max( + default_page.getModificationDate(), + max_content_modification_date, + ) + if context.getModificationDate() < max_content_modification_date: + error_list.append( + "Web Section {} is older than default page".format( + context.getRelativeUrl())) + if fixit: + portal.portal_workflow.doActionFor( + context, + 'edit_action', + comment=translateString('Edited Web Section, it was older than default page')) + +return error_list diff --git a/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web/WebSection_checkDefaultPageModificationDateConsistency.xml b/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web/WebSection_checkDefaultPageModificationDateConsistency.xml new file mode 100644 index 0000000000000000000000000000000000000000..acdb16633393682772a2111fae87bf5ac3dd2d04 --- /dev/null +++ b/bt5/erp5_web/SkinTemplateItem/portal_skins/erp5_web/WebSection_checkDefaultPageModificationDateConsistency.xml @@ -0,0 +1,62 @@ +<?xml version="1.0"?> +<ZopeData> + <record id="1" aka="AAAAAAAAAAE="> + <pickle> + <global name="PythonScript" module="Products.PythonScripts.PythonScript"/> + </pickle> + <pickle> + <dictionary> + <item> + <key> <string>Script_magic</string> </key> + <value> <int>3</int> </value> + </item> + <item> + <key> <string>_bind_names</string> </key> + <value> + <object> + <klass> + <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> + </klass> + <tuple/> + <state> + <dictionary> + <item> + <key> <string>_asgns</string> </key> + <value> + <dictionary> + <item> + <key> <string>name_container</string> </key> + <value> <string>container</string> </value> + </item> + <item> + <key> <string>name_context</string> </key> + <value> <string>context</string> </value> + </item> + <item> + <key> <string>name_m_self</string> </key> + <value> <string>script</string> </value> + </item> + <item> + <key> <string>name_subpath</string> </key> + <value> <string>traverse_subpath</string> </value> + </item> + </dictionary> + </value> + </item> + </dictionary> + </state> + </object> + </value> + </item> + <item> + <key> <string>_params</string> </key> + <value> <string>fixit=False</string> </value> + </item> + <item> + <key> <string>id</string> </key> + <value> <string>WebSection_checkDefaultPageModificationDateConsistency</string> </value> + </item> + </dictionary> + </pickle> + </record> +</ZopeData> diff --git a/bt5/erp5_web/bt/template_portal_type_property_sheet_list b/bt5/erp5_web/bt/template_portal_type_property_sheet_list index 0bb6c5f8a76ebffc810ce31a4156e2f80b514305..e18acb68e8dbb0c4c3e19fd39dcf4032db881bab 100644 --- a/bt5/erp5_web/bt/template_portal_type_property_sheet_list +++ b/bt5/erp5_web/bt/template_portal_type_property_sheet_list @@ -1,6 +1,10 @@ Static Web Section | SortIndex +Static Web Section | WebSectionUpgradeConstraint +Static Web Site | WebSectionUpgradeConstraint Static Web Site | WebSitePreference Web Page | Reference Web Page | SortIndex Web Section | SortIndex +Web Section | WebSectionUpgradeConstraint +Web Site | WebSectionUpgradeConstraint Web Site | WebSitePreference \ No newline at end of file diff --git a/bt5/erp5_web/bt/template_property_sheet_id_list b/bt5/erp5_web/bt/template_property_sheet_id_list new file mode 100644 index 0000000000000000000000000000000000000000..64294fe7870b62207e814b4d5c9af8996b3b9b4a --- /dev/null +++ b/bt5/erp5_web/bt/template_property_sheet_id_list @@ -0,0 +1 @@ +WebSectionUpgradeConstraint \ No newline at end of file diff --git a/product/ERP5/tests/testERP5Web.py b/product/ERP5/tests/testERP5Web.py index fd474eece4c54f7bd67a41a87a2628732747630a..746e9c73fa3fb8728f0443fd18eab6549ad33db1 100644 --- a/product/ERP5/tests/testERP5Web.py +++ b/product/ERP5/tests/testERP5Web.py @@ -29,7 +29,7 @@ ############################################################################## import re -import unittest +import time from unittest import expectedFailure, skip from StringIO import StringIO from urllib import urlencode @@ -2114,11 +2114,81 @@ class TestERP5WebCategoryPublicationWorkflow(ERP5TypeTestCase): self.assertEqual([], self.category.getParentValue().contentValues()) -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestERP5Web)) - suite.addTest(unittest.makeSuite(TestERP5WebWithSimpleSecurity)) - suite.addTest(unittest.makeSuite(TestERP5WebCategoryPublicationWorkflow)) - suite.addTest(unittest.makeSuite(TestWebSiteTraversalHook)) - suite.addTest(unittest.makeSuite(TestWebSectionTraversalHook)) - return suite +class ERP5WebUpgraderMixin(object): + """Test mixin that checks that web site or web sections are upgraded. + + Subclasses must set `upgraded` attribute. + """ + upgraded = None # type: erp5.portal_type.WebSection + def getBusinessTemplateList(self): + return ('erp5_base', 'erp5_web', ) + + def test_empty_constraint(self): + self.assertEqual( + [], [str(m.getMessage()) for m in self.upgraded.checkConsistency()]) + + def test_upgrader_fix_modification_date(self): + # Upgrader sets the modification date on the web section if + # it's older than its default page. + html_page = self.portal.web_page_module.newContent( + portal_type='Web Page', + reference=self.id(), + ) + html_page.publish() + self.tic() + + self.upgraded.edit(aggregate_value=html_page) + self.tic() + time.sleep(1) + html_page.edit(text_content="<p>Hello again</p>") + self.tic() + self.assertLess( + self.upgraded.getModificationDate(), + html_page.getModificationDate() + ) + self.assertEqual( + ['Web Section {} is older than default page'.format(self.upgraded.getRelativeUrl())], + [str(m.getMessage()) for m in self.upgraded.checkConsistency()]) + self.upgraded.fixConsistency() + self.tic() + + self.assertEqual( + [], [str(m.getMessage()) for m in self.upgraded.checkConsistency()]) + self.assertGreater( + self.upgraded.getModificationDate(), + html_page.getModificationDate()) + + +class TestERP5WebSiteUpgrader(ERP5WebUpgraderMixin, ERP5TypeTestCase): + def afterSetUp(self): + super(ERP5WebUpgraderMixin, self).afterSetUp() + self.upgraded = self.portal.web_site_module.newContent( + portal_type='Web Site', + ) + + +class TestERP5WebSectionUpgrader(ERP5WebUpgraderMixin, ERP5TypeTestCase): + def afterSetUp(self): + super(ERP5WebUpgraderMixin, self).afterSetUp() + self.upgraded = self.portal.web_site_module.newContent( + portal_type='Web Site', + ).newContent( + portal_type='Web Section', + ) + +class TestERP5StaticWebSiteUpgrader(ERP5WebUpgraderMixin, ERP5TypeTestCase): + def afterSetUp(self): + super(ERP5WebUpgraderMixin, self).afterSetUp() + self.upgraded = self.portal.web_site_module.newContent( + portal_type='Static Web Site', + ) + + +class TestERP5StaticWebSectionUpgrader(ERP5WebUpgraderMixin, ERP5TypeTestCase): + def afterSetUp(self): + super(ERP5WebUpgraderMixin, self).afterSetUp() + self.upgraded = self.portal.web_site_module.newContent( + portal_type='Web Site', + ).newContent( + portal_type='Static Web Section', + )