Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Boxiang Sun
erp5
Commits
dfb15874
Commit
dfb15874
authored
Feb 05, 2021
by
Julien Muchembled
Browse files
Options
Browse Files
Download
Plain Diff
Add support for CMF 2.3
See merge request
nexedi/erp5!957
parents
989ad1fd
9f248dfc
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
467 additions
and
178 deletions
+467
-178
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testBusinessTemplate.py
...eItem/portal_components/test.erp5.testBusinessTemplate.py
+12
-12
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testERP5Core.py
...tTemplateItem/portal_components/test.erp5.testERP5Core.py
+9
-7
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testERP5Type.py
...tTemplateItem/portal_components/test.erp5.testERP5Type.py
+4
-2
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testFields.py
...estTemplateItem/portal_components/test.erp5.testFields.py
+0
-3
bt5/erp5_corporate_identity/SkinTemplateItem/portal_skins/erp5_corporate_identity/WebPage_finishPdfCreation.py
...kins/erp5_corporate_identity/WebPage_finishPdfCreation.py
+3
-1
bt5/erp5_csv_style/ActionTemplateItem/portal_types/portal_actions/csv_export.xml
...onTemplateItem/portal_types/portal_actions/csv_export.xml
+0
-0
bt5/erp5_csv_style/ActionTemplateItem/portal_types/portal_actions/csv_import.xml
...onTemplateItem/portal_types/portal_actions/csv_import.xml
+0
-0
bt5/erp5_csv_style/bt/template_action_path_list
bt5/erp5_csv_style/bt/template_action_path_list
+2
-2
bt5/erp5_dms/TestTemplateItem/portal_components/test.erp5.testDms.py
...s/TestTemplateItem/portal_components/test.erp5.testDms.py
+5
-6
bt5/erp5_dms/TestTemplateItem/portal_components/test.erp5.testWebDavSupport.py
...lateItem/portal_components/test.erp5.testWebDavSupport.py
+8
-6
bt5/erp5_forge/TestTemplateItem/portal_components/test.erp5.testTemplateTool.py
...plateItem/portal_components/test.erp5.testTemplateTool.py
+34
-5
product/ERP5/Document/BusinessTemplate.py
product/ERP5/Document/BusinessTemplate.py
+5
-2
product/ERP5/ERP5Site.py
product/ERP5/ERP5Site.py
+72
-73
product/ERP5/bootstrap/erp5_core/DocumentTemplateItem/portal_components/document.erp5.File.py
...umentTemplateItem/portal_components/document.erp5.File.py
+30
-11
product/ERP5/bootstrap/erp5_core/ModuleComponentTemplateItem/portal_components/module.erp5.WebDAVSupport.py
...mplateItem/portal_components/module.erp5.WebDAVSupport.py
+2
-1
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/ERP5Site_reindexAll.py
...emplateItem/portal_skins/erp5_core/ERP5Site_reindexAll.py
+0
-1
product/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/breadcrumbs.py
...TemplateItem/portal_skins/erp5_xhtml_style/breadcrumbs.py
+13
-15
product/ERP5OOo/tests/testFormPrintoutAsODG.py
product/ERP5OOo/tests/testFormPrintoutAsODG.py
+0
-1
product/ERP5OOo/tests/testFormPrintoutAsODT.py
product/ERP5OOo/tests/testFormPrintoutAsODT.py
+5
-6
product/ERP5OOo/tests/testOOoBatchMode.py
product/ERP5OOo/tests/testOOoBatchMode.py
+1
-1
product/ERP5OOo/tests/testOOoDynamicStyle.py
product/ERP5OOo/tests/testOOoDynamicStyle.py
+2
-2
product/ERP5Type/Base.py
product/ERP5Type/Base.py
+9
-5
product/ERP5Type/ZopePatch.py
product/ERP5Type/ZopePatch.py
+1
-0
product/ERP5Type/__init__.py
product/ERP5Type/__init__.py
+15
-0
product/ERP5Type/dynamic/portal_type_class.py
product/ERP5Type/dynamic/portal_type_class.py
+9
-0
product/ERP5Type/patches/CMFCoreSkinnable.py
product/ERP5Type/patches/CMFCoreSkinnable.py
+3
-5
product/ERP5Type/patches/CMFCoreUtils.py
product/ERP5Type/patches/CMFCoreUtils.py
+5
-4
product/ERP5Type/patches/CookieCrumbler.py
product/ERP5Type/patches/CookieCrumbler.py
+172
-6
product/ERP5Type/patches/DynamicType.py
product/ERP5Type/patches/DynamicType.py
+26
-0
product/ERP5Type/patches/Restricted.py
product/ERP5Type/patches/Restricted.py
+3
-1
product/ERP5Type/patches/WorkflowTool.py
product/ERP5Type/patches/WorkflowTool.py
+13
-0
product/ERP5Type/tests/ERP5TypeTestCase.py
product/ERP5Type/tests/ERP5TypeTestCase.py
+4
-0
No files found.
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testBusinessTemplate.py
View file @
dfb15874
...
...
@@ -6899,17 +6899,17 @@ class TestBusinessTemplate(BusinessTemplateMixin):
Updating from:
portal_categories/test_category/modified
portal_categories/test_category/modified/container_in_which_child_is_added
portal_categories/test_category/modified/container_in_which_child_is_added/child_kept
portal_categories/test_category/modified/removed
portal_categories/test_category/modified
_category
portal_categories/test_category/modified
_category
/container_in_which_child_is_added
portal_categories/test_category/modified
_category
/container_in_which_child_is_added/child_kept
portal_categories/test_category/modified
_category
/removed
to:
portal_categories/test_category/modified <-- this will be modified
portal_categories/test_category/modified/container_in_which_child_is_added
portal_categories/test_category/modified/container_in_which_child_is_added/child_kept
portal_categories/test_category/modified/container_in_which_child_is_added/added
portal_categories/test_category/modified
_category
<-- this will be modified
portal_categories/test_category/modified
_category
/container_in_which_child_is_added
portal_categories/test_category/modified
_category
/container_in_which_child_is_added/child_kept
portal_categories/test_category/modified
_category
/container_in_which_child_is_added/added
was causing when test_category was added both as a base category and as paths.
...
...
@@ -6920,7 +6920,7 @@ class TestBusinessTemplate(BusinessTemplateMixin):
portal_categories
.
manage_delObjects
([
'test_category'
])
base_category
=
portal_categories
.
newContent
(
portal_type
=
'Base Category'
,
id
=
'test_category'
)
parent_category
=
base_category
.
newContent
(
portal_type
=
'Category'
,
id
=
'modified'
)
parent_category
=
base_category
.
newContent
(
portal_type
=
'Category'
,
id
=
'modified
_category
'
)
parent_category
.
newContent
(
portal_type
=
'Category'
,
id
=
'container_in_which_child_is_added'
)
parent_category
.
newContent
(
portal_type
=
'Category'
,
id
=
'removed'
)
parent_category
.
container_in_which_child_is_added
.
newContent
(
portal_type
=
'Category'
,
id
=
'child_kept'
)
...
...
@@ -6945,7 +6945,7 @@ class TestBusinessTemplate(BusinessTemplateMixin):
shutil
.
rmtree
(
export_dir
)
# Apply the changes and build a second version of business template
parent_category
.
setTitle
(
'modified'
)
parent_category
.
setTitle
(
'modified
_category
'
)
parent_category
.
container_in_which_child_is_added
.
newContent
(
portal_type
=
'Category'
,
id
=
'added'
)
parent_category
.
manage_delObjects
([
'removed'
])
...
...
@@ -6959,7 +6959,7 @@ class TestBusinessTemplate(BusinessTemplateMixin):
self
.
tic
()
new_business_template_version_1
.
install
()
self
.
tic
()
portal_categories
.
test_category
.
modified
.
container_in_which_child_is_added
.
setTitle
(
portal_categories
.
test_category
.
modified
_category
.
container_in_which_child_is_added
.
setTitle
(
'This path should not be reinstalled during update'
)
self
.
tic
()
...
...
@@ -6971,7 +6971,7 @@ class TestBusinessTemplate(BusinessTemplateMixin):
self
.
tic
()
self
.
assertEqual
(
'This path should not be reinstalled during update'
,
portal_categories
.
test_category
.
modified
.
container_in_which_child_is_added
.
getTitle
())
portal_categories
.
test_category
.
modified
_category
.
container_in_which_child_is_added
.
getTitle
())
def
test_update_business_template_with_template_keep_path_list_catalog_method
(
self
):
"""Tests for `template_keep_path_list` feature for the special case of catalog methods
...
...
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testERP5Core.py
View file @
dfb15874
...
...
@@ -576,7 +576,7 @@ class TestERP5Core(ERP5TypeTestCase, ZopeTestCase.Functional):
if
i
.
getId
()
not
in
(
'portal_uidhandler'
,)
and
0
!=
i
.
getUid
()
!=
i
.
getProperty
(
'uid'
)])
def
test_site_manager_and_translation_migration
(
self
):
def
test_
04_
site_manager_and_translation_migration
(
self
):
from
zope.site.hooks
import
getSite
,
setSite
from
zope.component
import
queryUtility
from
zope.i18n.interfaces
import
ITranslationDomain
...
...
@@ -594,25 +594,27 @@ class TestERP5Core(ERP5TypeTestCase, ZopeTestCase.Functional):
self
.
assertEqual
(
queryUtility
(
ITranslationDomain
,
'ui'
),
None
)
# now let's simulate a site just migrated from Zope 2.8 that's being
# accessed for the first time:
old_site
=
getSite
()
try
:
from
Products.ERP5
import
ERP5Site
if
1
:
# BBB
setSite
()
# Sites from Zope2.8 don't have a site_manager yet.
del
self
.
portal
.
_components
self
.
assertIsNotNone
(
ERP5Site
.
_missing_tools_registered
)
ERP5Site
.
_missing_tools_registered
=
None
self
.
commit
()
# check that we can't get any translation utility
self
.
assertEqual
(
queryUtility
(
ITranslationDomain
,
'erp5_ui'
),
None
)
# Now simulate first access. Default behaviour from
# ObjectManager is to raise a ComponentLookupError here:
setSite
(
self
.
portal
)
self
.
commit
()
self
.
assertIsNotNone
(
ERP5Site
.
_missing_tools_registered
)
# This should have automatically reconstructed the i18n utility
# registrations:
self
.
assertEqual
(
queryUtility
(
ITranslationDomain
,
'erp5_ui'
),
erp5_ui_catalog
)
self
.
assertEqual
(
queryUtility
(
ITranslationDomain
,
'ui'
),
erp5_ui_catalog
)
finally
:
# clean everything up, we don't want to mess the test environment
self
.
abort
()
setSite
(
old_site
)
def
test_BasicAuthenticateDesactivated
(
self
):
"""Make sure Unauthorized error does not lead to Basic auth popup in browser"""
...
...
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testERP5Type.py
View file @
dfb15874
...
...
@@ -52,6 +52,7 @@ from AccessControl.ZopeGuards import guarded_getattr, guarded_hasattr
from
Products.ERP5Type.tests.utils
import
createZODBPythonScript
from
Products.ERP5Type.tests.utils
import
removeZODBPythonScript
from
Products.ERP5Type
import
Permissions
from
DateTime
import
DateTime
class
PropertySheetTestCase
(
ERP5TypeTestCase
):
"""Base test case class for property sheets tests.
...
...
@@ -2478,8 +2479,9 @@ class TestERP5Type(PropertySheetTestCase, LogInterceptor):
portal
=
self
.
getPortalObject
()
folder
=
self
.
getOrganisationModule
()
obj
=
folder
.
newContent
(
portal_type
=
'Organisation'
)
self
.
assertNotEquals
(
obj
.
getCreationDate
(),
portal
.
CreationDate
())
self
.
assertNotEquals
(
obj
.
getCreationDate
(),
folder
.
getCreationDate
())
self
.
assertIsInstance
(
portal
.
creation_date
,
DateTime
)
self
.
assertLess
(
portal
.
creation_date
,
obj
.
getCreationDate
())
self
.
assertIsNone
(
folder
.
getCreationDate
())
def
test_copyWithoutModificationRight
(
self
):
"""
...
...
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testFields.py
View file @
dfb15874
...
...
@@ -638,9 +638,6 @@ class TestProxyField(ERP5TypeTestCase):
self
.
container
=
Folder
(
'container'
).
__of__
(
self
.
portal
)
self
.
container
.
manage_addProduct
[
'ERP5Form'
].
addERP5Form
(
'Base_viewProxyFieldLibrary'
,
'Proxys'
)
self
.
container
.
manage_addProduct
[
'ERP5Form'
].
addERP5Form
(
'Base_view'
,
'View'
)
from
Products.CMFCore.tests.base.utils
import
_setUpDefaultTraversable
_setUpDefaultTraversable
()
def
addField
(
self
,
form
,
id_
,
title
,
field_type
):
form
.
manage_addField
(
id_
,
title
,
field_type
)
...
...
bt5/erp5_corporate_identity/SkinTemplateItem/portal_skins/erp5_corporate_identity/WebPage_finishPdfCreation.py
View file @
dfb15874
...
...
@@ -17,6 +17,8 @@ Save, download or return generated PDF Document
# doc_pdf_file pdf content to store
# doc_aggregate_list not applicable (only used for events)
from
io
import
BytesIO
if
doc_save
:
dms_module
=
getattr
(
context
,
'document_module'
,
None
)
if
dms_module
is
not
None
:
...
...
@@ -31,7 +33,7 @@ if doc_save:
)
document
.
edit
(
source_reference
=
''
.
join
([
doc_reference
,
'.pdf'
]),
file
=
doc_pdf_file
file
=
BytesIO
(
doc_pdf_file
)
)
document
.
setContentType
(
"application/pdf"
)
...
...
bt5/erp5_csv_style/ActionTemplateItem/portal_types/portal_
propertie
s/csv_export.xml
→
bt5/erp5_csv_style/ActionTemplateItem/portal_types/portal_
action
s/csv_export.xml
View file @
dfb15874
File moved
bt5/erp5_csv_style/ActionTemplateItem/portal_types/portal_
propertie
s/csv_import.xml
→
bt5/erp5_csv_style/ActionTemplateItem/portal_types/portal_
action
s/csv_import.xml
View file @
dfb15874
File moved
bt5/erp5_csv_style/bt/template_action_path_list
View file @
dfb15874
portal_properties | csv_export
portal_properties | csv_import
\ No newline at end of file
portal_actions | csv_export
portal_actions | csv_import
\ No newline at end of file
bt5/erp5_dms/TestTemplateItem/portal_components/test.erp5.testDms.py
View file @
dfb15874
...
...
@@ -672,10 +672,9 @@ class TestDocument(TestDocumentMixin):
for
document_type
in
portal
.
getPortalDocumentTypeList
():
module
=
portal
.
getDefaultModule
(
document_type
)
obj
=
module
.
newContent
(
portal_type
=
document_type
)
self
.
assertNotEquals
(
obj
.
getCreationDate
(),
module
.
getCreationDate
())
self
.
assertNotEquals
(
obj
.
getCreationDate
(),
portal
.
CreationDate
())
self
.
assertIsInstance
(
portal
.
creation_date
,
DateTime
)
self
.
assertLess
(
portal
.
creation_date
,
obj
.
getCreationDate
())
self
.
assertIsNone
(
module
.
getCreationDate
())
def
test_06_ProcessingStateOfAClonedDocument
(
self
):
"""
...
...
@@ -2865,7 +2864,7 @@ class TestDocumentWithSecurity(TestDocumentMixin):
reference
=
'Foo_001'
,
title
=
'Foo_OO1'
)
f
=
makeFileUpload
(
'Foo_001.odt'
)
text_document
.
edit
(
file
=
f
.
read
()
)
text_document
.
edit
(
file
=
f
)
f
.
close
()
self
.
tic
()
...
...
@@ -2967,4 +2966,4 @@ def test_suite():
return
suite
# vim: syntax=python shiftwidth=2
\ No newline at end of file
# vim: syntax=python shiftwidth=2
bt5/erp5_dms/TestTemplateItem/portal_components/test.erp5.testWebDavSupport.py
View file @
dfb15874
...
...
@@ -186,12 +186,14 @@ class TestWebDavSupport(ERP5TypeTestCase):
"""
iso_text_content
=
text_content
.
decode
(
'utf-8'
).
encode
(
'iso-8859-1'
)
path
=
web_page_module
.
getPath
()
response
=
self
.
publish
(
'%s/%s'
%
(
path
,
filename
),
request_method
=
'PUT'
,
stdin
=
StringIO
(
iso_text_content
),
basic
=
self
.
authentication
)
self
.
assertEqual
(
response
.
getStatus
(),
httplib
.
NO_CONTENT
)
self
.
assertEqual
(
web_page_module
[
filename
].
getData
(),
iso_text_content
)
for
_
in
xrange
(
2
):
# Run twice to check the code that compares
# old & new data when setting file attribute.
response
=
self
.
publish
(
'%s/%s'
%
(
path
,
filename
),
request_method
=
'PUT'
,
stdin
=
StringIO
(
iso_text_content
),
basic
=
self
.
authentication
)
self
.
assertEqual
(
response
.
getStatus
(),
httplib
.
NO_CONTENT
)
self
.
assertEqual
(
web_page_module
[
filename
].
getData
(),
iso_text_content
)
# Convert to base format and run conversion into utf-8
self
.
tic
()
# Content-Type header is replaced if sonversion encoding succeed
...
...
bt5/erp5_forge/TestTemplateItem/portal_components/test.erp5.testTemplateTool.py
View file @
dfb15874
...
...
@@ -34,6 +34,7 @@ import random
import
tempfile
from
xml.dom.minidom
import
getDOMImplementation
from
App.config
import
getConfiguration
from
Products.CMFCore.ActionsTool
import
ActionsTool
from
Products.ERP5.Document.BusinessTemplate
import
\
BusinessTemplateMissingDependency
...
...
@@ -51,7 +52,6 @@ class TestTemplateTool(ERP5TypeTestCase):
return
(
'erp5_core_proxy_field_legacy'
,
'erp5_full_text_mroonga_catalog'
,
'erp5_base'
,
'erp5_csv_style'
,
'erp5_crm'
,
'erp5_forge'
)
...
...
@@ -140,7 +140,7 @@ class TestTemplateTool(ERP5TypeTestCase):
self
.
assertEqual
(
test_web
.
getTitle
(),
'test_web'
)
self
.
assertEqual
(
len
(
test_web
.
getRevision
()),
28
)
def
test_updateBusinessTemplateFromUrl_simple
(
self
):
def
test_
00_
updateBusinessTemplateFromUrl_simple
(
self
):
"""
Test updateBusinessTemplateFromUrl method
...
...
@@ -148,13 +148,42 @@ class TestTemplateTool(ERP5TypeTestCase):
the new bt5 is not installed, only imported.
"""
self
.
_svn_setup_ssl
()
global
PropertiesTool
class
PropertiesTool
(
ActionsTool
):
id
=
'portal_properties'
cls
=
PropertiesTool
# Assign a fake properties tool to the portal
tool
=
PropertiesTool
()
self
.
portal
.
_setObject
(
tool
.
id
,
tool
,
set_owner
=
False
,
suppress_events
=
True
)
del
tool
self
.
commit
()
template_tool
=
self
.
portal
.
portal_templates
url
=
'https://svn.erp5.org/repos/public/erp5/trunk/bt5/erp5_csv_style'
template_tool
.
updateBusinessTemplateFromUrl
(
url
)
old_bt
=
template_tool
.
getInstalledBusinessTemplate
(
'erp5_csv_style'
)
# fake different revision
old_bt
.
setRevision
(
''
)
url
=
'https://svn.erp5.org/repos/public/erp5/trunk/bt5/erp5_csv_style'
template_tool
.
updateBusinessTemplateFromUrl
(
url
)
new_bt
=
template_tool
.
getInstalledBusinessTemplate
(
'erp5_csv_style'
)
# Break the properties tool
self
.
assertIs
(
self
.
portal
.
portal_properties
.
__class__
,
cls
)
self
.
commit
()
self
.
portal
.
_p_jar
.
cacheMinimize
()
del
PropertiesTool
self
.
assertIsNot
(
self
.
portal
.
portal_properties
.
__class__
,
cls
)
# Remove portal.portal_properties
from
Products.ERP5Type.dynamic.portal_type_class
import
\
_bootstrapped
,
synchronizeDynamicModules
_bootstrapped
.
remove
(
self
.
portal
.
id
)
synchronizeDynamicModules
(
self
.
portal
,
force
=
True
)
# The bt from this repo
url
=
self
.
_getBTPathAndIdList
((
'erp5_csv_style'
,))[
0
][
0
]
new_bt
=
template_tool
.
updateBusinessTemplateFromUrl
(
url
)
self
.
assertNotEquals
(
old_bt
,
new_bt
)
self
.
assertEqual
(
'erp5_csv_style'
,
new_bt
.
getTitle
())
...
...
product/ERP5/Document/BusinessTemplate.py
View file @
dfb15874
...
...
@@ -1869,6 +1869,7 @@ class ToolTemplateItem(PathTemplateItem):
def
install
(
self
,
context
,
trashbin
,
**
kw
):
""" When we install a tool that is a type provider not
registered on types tool, register it into the type provider.
We also need to register the tool on the site manager
"""
PathTemplateItem
.
install
(
self
,
context
,
trashbin
,
**
kw
)
portal
=
context
.
getPortalObject
()
...
...
@@ -1879,6 +1880,8 @@ class ToolTemplateItem(PathTemplateItem):
type_container_id
not
in
types_tool
.
type_provider_list
):
types_tool
.
type_provider_list
=
tuple
(
types_tool
.
type_provider_list
)
+
\
(
type_container_id
,)
tool_id_list
=
list
(
set
(
self
.
_objects
.
keys
())
&
set
(
portal
.
_registry_tool_id_list
))
portal
.
_registerTools
(
tool_id_list
)
def
uninstall
(
self
,
context
,
**
kw
):
""" When we uninstall a tool, unregister it from the type provider. """
...
...
@@ -2121,7 +2124,7 @@ class RegisteredSkinSelectionTemplateItem(BaseTemplateItem):
update_dict
=
kw
.
get
(
'object_to_update'
)
force
=
kw
.
get
(
'force'
)
portal
=
context
.
getPortalObject
()
skin_tool
=
getToolByName
(
portal
,
'portal_skins'
)
skin_tool
=
portal
.
portal_skins
for
skin_folder_id
in
self
.
_objects
.
keys
():
...
...
@@ -2163,7 +2166,7 @@ class RegisteredSkinSelectionTemplateItem(BaseTemplateItem):
def
uninstall
(
self
,
context
,
**
kw
):
portal
=
context
.
getPortalObject
()
skin_tool
=
getToolByName
(
portal
,
'portal_skins'
)
skin_tool
=
portal
.
portal_skins
object_path
=
kw
.
get
(
'object_path'
)
for
skin_folder_id
in
(
object_path
,)
if
object_path
else
self
.
_objects
:
skin_selection_list
=
self
.
_objects
[
skin_folder_id
]
...
...
product/ERP5/ERP5Site.py
View file @
dfb15874
...
...
@@ -15,6 +15,8 @@
Portal class
"""
from
DateTime
import
DateTime
from
six.moves
import
map
import
thread
,
threading
from
weakref
import
ref
as
weakref
from
OFS.Application
import
Application
,
AppInitializer
...
...
@@ -25,7 +27,7 @@ from Products.SiteErrorLog.SiteErrorLog import manage_addErrorLog
from
ZPublisher
import
BeforeTraverse
from
ZPublisher.BaseRequest
import
RequestContainer
from
AccessControl
import
ClassSecurityInfo
from
Products.CMF
Default.Portal
import
CMFSit
e
from
Products.CMF
Core.PortalObject
import
PortalObjectBas
e
from
Products.ERP5Type
import
Permissions
from
Products.ERP5Type.Core.Folder
import
FolderMixIn
from
Acquisition
import
aq_base
...
...
@@ -36,7 +38,8 @@ from Products.ERP5Type.ERP5Type import ERP5TypeInformation
from
Products.ERP5Type.patches.CMFCoreSkinnable
import
SKINDATA
,
skinResolve
from
Products.CMFActivity.Errors
import
ActivityPendingError
import
ERP5Defaults
from
Products.ERP5Type.TransactionalVariable
import
getTransactionalVariable
from
Products.ERP5Type.TransactionalVariable
import
\
getTransactionalVariable
,
TransactionalResource
from
Products.ERP5Type.dynamic.portal_type_class
import
synchronizeDynamicModules
from
Products.ERP5Type.mixin.response_header_generator
import
ResponseHeaderGenerator
...
...
@@ -227,8 +230,9 @@ class _site(threading.local):
getSite
,
setSite
=
_site
()
_missing_tools_registered
=
None
class
ERP5Site
(
ResponseHeaderGenerator
,
FolderMixIn
,
CMFSit
e
,
CacheCookieMixin
):
class
ERP5Site
(
ResponseHeaderGenerator
,
FolderMixIn
,
PortalObjectBas
e
,
CacheCookieMixin
):
"""
The *only* function this class should have is to help in the setup
of a new ERP5. It should not assist in the functionality at all.
...
...
@@ -269,6 +273,15 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
def
__init__
(
self
,
id
):
PortalObjectBase
.
__init__
(
self
,
id
)
self
.
creation_date
=
DateTime
()
security
.
declarePrivate
(
'reindexObject'
)
def
reindexObject
(
self
,
idxs
=
[]):
"""from Products.CMFDefault.Portal"""
pass
security
.
declarePublic
(
'isSubtreeIndexable'
)
def
isSubtreeIndexable
(
self
):
"""
...
...
@@ -328,7 +341,7 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
from
Products.Localizer.MessageCatalog
import
(
message_catalog_alias_sources
)
sm
=
self
.
getSiteManager
()
sm
=
self
.
_components
for
message_catalog
in
self
.
Localizer
.
objectValues
():
sm
.
registerUtility
(
message_catalog
,
provided
=
ITranslationDomain
,
...
...
@@ -338,21 +351,31 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
provided
=
ITranslationDomain
,
name
=
alias
)
def
_doInitialSiteManagerMigration
(
self
):
self
.
_createInitialSiteManager
()
# Now that we have a sitemanager, se can do things that require
# one. Including setting up ZTK style utilities and adapters. We
# can even call setSite(self), as long as we roll back that later,
# since we are actually in the middle of a setSite() call.
from
zope.site.hooks
import
getSite
,
setSite
old_site
=
getSite
()
try
:
setSite
(
self
)
# setSite(self) is not really necessary for the migration below, but
# could be needed by other migrations to be added here.
self
.
_doTranslationDomainRegistration
()
finally
:
setSite
(
old_site
)
_registry_tool_id_list
=
'caching_policy_manager'
,
def
_registerMissingTools
(
self
):
tool_id_list
=
(
"portal_skins"
,
"portal_types"
,
"portal_membership"
,
"portal_url"
,
"portal_workflow"
)
if
(
None
in
map
(
self
.
get
,
tool_id_list
)
or
not
TransactionalResource
.
registerOnce
(
__name__
,
'site_manager'
,
self
.
id
)):
return
self
.
_registerTools
(
tool_id_list
+
self
.
_registry_tool_id_list
)
def
markRegistered
(
txn
):
global
_missing_tools_registered
_missing_tools_registered
=
self
.
id
TransactionalResource
(
tpc_finish
=
markRegistered
)
def
_registerTools
(
self
,
tool_id_list
):
from
Products.CMFCore
import
interfaces
,
utils
sm
=
self
.
_components
for
tool_id
in
tool_id_list
:
tool
=
self
.
get
(
tool_id
,
None
)
if
tool
:
tool_interface
=
utils
.
_tool_interface_registry
.
get
(
tool_id
)
if
tool_interface
is
not
None
:
# Note: already registered tools will be either:
# - updated
# - registered again after being unregistered
sm
.
registerUtility
(
aq_base
(
tool
),
tool_interface
)
# backward compatibility auto-migration
def
getSiteManager
(
self
):
...
...
@@ -369,14 +392,29 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
# OFS.ObjectManager.ObjectManager.getSiteManager(), and is exactly
# as cheap as it is on the case that self._components is already
# set.
if
self
.
id
==
_missing_tools_registered
:
return
self
.
_components
# fast path
_components
=
self
.
_components
if
_components
is
not
None
:
return
_components
# This method below can take as (reasonably) long as it pleases
# since it will not be run ever again
self
.
_doInitialSiteManagerMigration
()
assert
self
.
_components
is
not
None
,
'Migration Failed!'
return
self
.
_components
if
_components
is
None
:
# only create _components
self
.
_createInitialSiteManager
()
_components
=
self
.
_components
# Now that we have a sitemanager, se can do things that require
# one. Including setting up ZTK style utilities and adapters. We
# can even call setSite(self), as long as we roll back that later,
# since we are actually in the middle of a setSite() call.
from
zope.site.hooks
import
getSite
,
setSite
old_site
=
getSite
()
try
:
setSite
(
self
)
self
.
_doTranslationDomainRegistration
()
self
.
_registerMissingTools
()
finally
:
setSite
(
old_site
)
else
:
self
.
_registerMissingTools
()
return
_components
security
.
declareProtected
(
Permissions
.
View
,
'view'
)
def
view
(
self
):
...
...
@@ -387,7 +425,7 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
return
self
.
index_html
()
def
__of__
(
self
,
parent
):
self
=
CMFSit
e
.
__of__
(
self
,
parent
)
self
=
PortalObjectBas
e
.
__of__
(
self
,
parent
)
# Use a transactional variable for performance reason,
# since ERP5Site.__of__ is called quite often.
tv
=
getTransactionalVariable
()
...
...
@@ -471,7 +509,7 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
path_item_list
=
path_item_list
,
new_id
=
new_id
)
# Rename the object
return
CMFSit
e
.
manage_renameObject
(
self
,
id
=
id
,
new_id
=
new_id
,
return
PortalObjectBas
e
.
manage_renameObject
(
self
,
id
=
id
,
new_id
=
new_id
,
REQUEST
=
REQUEST
)
...
...
@@ -589,7 +627,7 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
# _getProperty is missing, but since there are no protected properties
# on an ERP5 Site, we can just use getProperty instead.
_getProperty
=
CMFSit
e
.
getProperty
_getProperty
=
PortalObjectBas
e
.
getProperty
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getUid'
)
def
getUid
(
self
):
...
...
@@ -703,7 +741,7 @@ class ERP5Site(ResponseHeaderGenerator, FolderMixIn, CMFSite, CacheCookieMixin):
email_from_address
,
email_from_name
,
validate_email
):
CMFSit
e
.
setupDefaultProperties
(
self
,
p
,
title
,
description
,
PortalObjectBas
e
.
setupDefaultProperties
(
self
,
p
,
title
,
description
,
email_from_address
,
email_from_name
,
validate_email
)
...
...
@@ -1863,7 +1901,7 @@ factory_type_information = () # No original CMF portal_types installed by defaul
class
PortalGenerator
:
klass
=
CMFSit
e
klass
=
PortalObjectBas
e
def
setupTools
(
self
,
p
):
"""Set up initial tools"""
...
...
@@ -1872,29 +1910,13 @@ class PortalGenerator:
addCMFCoreTool
(
'CMF Actions Tool'
,
None
)
addCMFCoreTool
(
'CMF Catalog'
,
None
)
addCMFCoreTool
(
'CMF Member Data Tool'
,
None
)
addCMFCoreTool
(
'CMF Membership Tool'
,
None
)
addCMFCoreTool
(
'CMF Registration Tool'
,
None
)
addCMFCoreTool
(
'CMF Skins Tool'
,
None
)
addCMFCoreTool
(
'CMF Undo Tool'
,
None
)
addCMFCoreTool
(
'CMF URL Tool'
,
None
)
addCMFCoreTool
(
'CMF Workflow Tool'
,
None
)
addCMFDefaultTool
=
p
.
manage_addProduct
[
'CMFDefault'
].
manage_addTool
addCMFDefaultTool
(
'Default Discussion Tool'
,
None
)
addCMFDefaultTool
(
'Default Membership Tool'
,
None
)
addCMFDefaultTool
(
'Default Registration Tool'
,
None
)
addCMFDefaultTool
(
'Default Properties Tool'
,
None
)
addCMFDefaultTool
(
'Default Metadata Tool'
,
None
)
addCMFDefaultTool
(
'Default Syndication Tool'
,
None
)
# try to install CMFUid without raising exceptions if not available
try
:
addCMFUidTool
=
p
.
manage_addProduct
[
'CMFUid'
].
manage_addTool
except
AttributeError
:
pass
else
:
addCMFUidTool
(
'Unique Id Annotation Tool'
,
None
)
addCMFUidTool
(
'Unique Id Generator Tool'
,
None
)
addCMFUidTool
(
'Unique Id Handler Tool'
,
None
)
def
setupMailHost
(
self
,
p
):
p
.
manage_addProduct
[
'MailHost'
].
manage_addMailHost
(
'MailHost'
,
smtp_host
=
'localhost'
)
...
...
@@ -2194,8 +2216,6 @@ class ERP5Generator(PortalGenerator):
'manage_members'
))
# actions tool
removeActionsFromTool
(
p
.
portal_actions
,
(
'folderContents'
,))
# properties tool
removeActionsFromTool
(
p
.
portal_properties
,
(
'configPortal'
,))
# remove unused action providers
for
i
in
(
'portal_registration'
,
'portal_discussion'
,
'portal_syndication'
):
p
.
portal_actions
.
deleteActionProvider
(
i
)
...
...
@@ -2206,35 +2226,14 @@ class ERP5Generator(PortalGenerator):
"""
pass
# this lists only the skin layers of Products.CMFDefault we are actually
# interested in.
CMFDEFAULT_FOLDER_LIST
=
[
'Images'
]
def
addCMFDefaultDirectoryViews
(
self
,
p
):
"""Semi-manually create DirectoryViews since CMFDefault 2.X no longer
registers the "skins" directory, only its subdirectories, making it
unusable with Products.CMFCore.DirectoryView.addDirectoryViews."""
from
Products.CMFCore.DirectoryView
import
createDirectoryView
,
_generateKey
import
Products.CMFDefault
ps
=
p
.
portal_skins
# get the layer directories actually present
for
cmfdefault_skin_layer
in
self
.
CMFDEFAULT_FOLDER_LIST
:
reg_key
=
_generateKey
(
Products
.
CMFDefault
.
__name__
,
'skins/'
+
cmfdefault_skin_layer
)
createDirectoryView
(
ps
,
reg_key
)
def
setupDefaultSkins
(
self
,
p
):
ps
=
p
.
portal_skins
self
.
addCMFDefaultDirectoryViews
(
p
)
ps
.
manage_addProduct
[
'OFSP'
].
manage_addFolder
(
id
=
'external_method'
)
ps
.
manage_addProduct
[
'OFSP'
].
manage_addFolder
(
id
=
'custom'
)
# Set the 'custom' layer a high priority, so it remains the first
# layer when installing new business templates.
ps
[
'custom'
].
manage_addProperty
(
"business_template_skin_layer_priority"
,
100.0
,
"float"
)
skin_folder_list
=
[
'custom'
,
'external_method'
]
+
self
.
CMFDEFAULT_FOLDER_LIST
skin_folders
=
', '
.
join
(
skin_folder_list
)
skin_folders
=
', '
.
join
((
'custom'
,
'external_method'
))
ps
.
addSkinSelection
(
'View'
,
skin_folders
,
make_default
=
1
...
...
product/ERP5/bootstrap/erp5_core/DocumentTemplateItem/portal_components/document.erp5.File.py
View file @
dfb15874
...
...
@@ -34,8 +34,9 @@ from erp5.component.document.Document import Document, VALID_TEXT_FORMAT_LIST
from
erp5.component.document.Document
import
VALID_IMAGE_FORMAT_LIST
from
erp5.component.document.Document
import
ConversionError
from
Products.ERP5Type.Base
import
Base
,
removeIContentishInterface
from
Products.CMFDefault.File
import
File
as
CMF
File
from
OFS.Image
import
File
as
OFS_
File
from
Products.ERP5Type.Utils
import
deprecated
from
cStringIO
import
StringIO
def
_unpackData
(
data
):
"""
...
...
@@ -46,7 +47,7 @@ def _unpackData(data):
_MARKER
=
object
()
class
File
(
Document
,
CMF
File
):
class
File
(
Document
,
OFS_
File
):
"""
A File can contain raw data which can be uploaded and downloaded.
It is the root class of Image, OOoDocument (ERP5OOo product),
...
...
@@ -110,8 +111,14 @@ class File(Document, CMFFile):
filename
=
kw
.
get
(
'filename'
)
if
filename
:
self
.
_setFilename
(
filename
)
if
self
.
_isNotEmpty
(
file_object
):
self
.
_setFile
(
file_object
,
precondition
=
precondition
)
if
file_object
is
not
None
:
# XXX: Rather than doing nothing if empty, consider changing:
# - _update_image_info to clear metadata
# - interactions to do nothing (or else?)
file_object
.
seek
(
0
,
2
)
if
file_object
.
tell
():
file_object
.
seek
(
0
)
self
.
_setFile
(
file_object
)
Base
.
_edit
(
self
,
**
kw
)
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'edit'
)
...
...
@@ -138,11 +145,18 @@ class File(Document, CMFFile):
return
None
def
_setFile
(
self
,
data
,
precondition
=
None
):
if
data
is
not
None
and
self
.
hasData
()
and
\
str
(
data
.
read
())
==
str
(
self
.
getData
()):
# Same data as previous, no need to change it's content
if
data
is
None
:
return
CMFFile
.
_edit
(
self
,
precondition
=
precondition
,
file
=
data
)
if
self
.
hasData
():
if
str
(
data
.
read
())
==
str
(
self
.
getData
()):
# Same data as previous, no need to change its content
return
else
:
data
.
seek
(
0
,
2
)
if
data
.
tell
():
data
.
seek
(
0
)
self
.
manage_upload
(
data
)
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'setFile'
)
def
setFile
(
self
,
data
,
precondition
=
None
):
...
...
@@ -176,11 +190,16 @@ class File(Document, CMFFile):
return
str
(
data
)
# DAV Support
PUT
=
CMFFile
.
PUT
security
.
declareProtected
(
Permissions
.
ModifyPortalContent
,
'PUT'
)
def
PUT
(
self
,
REQUEST
,
RESPONSE
):
"""from Products.CMFDefault.File"""
OFS_File
.
PUT
(
self
,
REQUEST
,
RESPONSE
)
self
.
reindexObject
()
security
.
declareProtected
(
Permissions
.
FTPAccess
,
'manage_FTPstat'
,
'manage_FTPlist'
)
manage_FTPlist
=
CMF
File
.
manage_FTPlist
manage_FTPstat
=
CMF
File
.
manage_FTPstat
manage_FTPlist
=
OFS_
File
.
manage_FTPlist
manage_FTPstat
=
OFS_
File
.
manage_FTPstat
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getMimeTypeAndContent'
)
def
getMimeTypeAndContent
(
self
):
...
...
product/ERP5/bootstrap/erp5_core/ModuleComponentTemplateItem/portal_components/module.erp5.WebDAVSupport.py
View file @
dfb15874
...
...
@@ -23,6 +23,7 @@ from Products.ERP5Type.Globals import InitializeClass
from
Products.ERP5Type
import
Permissions
from
Products.CMFCore.PortalContent
import
ResourceLockedError
from
zExceptions
import
Forbidden
from
cStringIO
import
StringIO
security
=
ModuleSecurityInfo
(
__name__
)
...
...
@@ -76,7 +77,7 @@ class TextContent:
headers
=
self
.
parseHeadersFromText
(
body
)
content_type
=
REQUEST
.
get_header
(
'Content-Type'
,
''
)
headers
.
setdefault
(
'content_type'
,
content_type
)
headers
[
'file'
]
=
body
headers
[
'file'
]
=
StringIO
(
body
)
self
.
_edit
(
**
headers
)
except
ResourceLockedError
:
transaction
.
abort
()
...
...
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/ERP5Site_reindexAll.py
View file @
dfb15874
...
...
@@ -85,7 +85,6 @@ print reindex(
'portal_classes'
,
'portal_preferences'
,
'portal_simulation'
,
'portal_uidhandler'
,
)
and
'inventory'
not
in
x
.
id
],
...
...
product/ERP5/bootstrap/erp5_xhtml_style/SkinTemplateItem/portal_skins/erp5_xhtml_style/breadcrumbs.py
View file @
dfb15874
"Modified version for ERP5 to append the default action (/view) in the URL."
from
Products.CMFCore.utils
import
getToolByName
ptool
=
getToolByName
(
script
,
'portal_properties'
)
utool
=
getToolByName
(
script
,
'portal_url'
)
portal
=
context
.
getPortalObject
()
utool
=
portal
.
portal_url
portal_url
=
utool
()
result
=
[]
param
=
int
(
context
.
REQUEST
.
get
(
'ignore_layout'
,
0
))
and
'?ignore_layout:int=1'
or
''
param
=
'?ignore_layout:int=1'
if
int
(
portal
.
REQUEST
.
get
(
'ignore_layout'
,
0
))
else
''
if
include_root
:
result
.
append
(
{
'id'
:
'root'
,
'title'
:
ptool
.
title
()
,
'url'
:
'%s/view%s'
%
(
portal_url
,
param
)
}
)
relative
=
utool
.
getRelativeContentPath
(
context
)
portal
=
utool
.
getPortalObject
()
result
=
[{
'id'
:
'root'
,
'title'
:
portal
.
title
,
'url'
:
'%s/view%s'
%
(
portal_url
,
param
),
}]
else
:
result
=
[]
obj
=
portal
now
=
[]
for
name
in
relative
:
for
name
in
utool
.
getRelativeContentPath
(
context
)
:
obj
=
obj
.
restrictedTraverse
(
name
)
now
.
append
(
name
)
title
=
(
getattr
(
obj
,
"getCompactTranslatedTitle"
,
lambda
:
None
)()
or
obj
.
getTitle
()
or
obj
.
getId
()
)
if
n
ot
name
=
=
'talkback'
:
if
n
ame
!
=
'talkback'
:
result
.
append
(
{
'id'
:
name
,
'title'
:
title
,
'url'
:
'%s/%s/view%s'
%
(
portal_url
,
'/'
.
join
(
now
),
param
)
...
...
product/ERP5OOo/tests/testFormPrintoutAsODG.py
View file @
dfb15874
...
...
@@ -69,7 +69,6 @@ class TestFormPrintoutAsODG(TestFormPrintoutMixin):
addStyleSheet
=
custom
.
manage_addProduct
[
'OFSP'
].
manage_addFile
if
custom
.
_getOb
(
'Foo_getODGStyleSheet'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Foo_getODGStyleSheet'
,
file
=
foo_file
,
title
=
''
,
precondition
=
''
,
content_type
=
'application/vnd.oasis.opendocument.graphics'
)
erp5OOo
=
custom
.
manage_addProduct
[
'ERP5OOo'
]
...
...
product/ERP5OOo/tests/testFormPrintoutAsODT.py
View file @
dfb15874
...
...
@@ -84,23 +84,22 @@ class TestFormPrintoutAsODT(TestFormPrintoutMixin):
addStyleSheet
=
custom
.
manage_addProduct
[
'OFSP'
].
manage_addFile
if
custom
.
_getOb
(
'Foo_getODTStyleSheet'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Foo_getODTStyleSheet'
,
file
=
foo_file
,
title
=
''
,
precondition
=
''
,
content_type
=
'application/vnd.oasis.opendocument.text'
)
content_type
=
'application/vnd.oasis.opendocument.text'
)
if
custom
.
_getOb
(
'Foo2_getODTStyleSheet'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Foo2_getODTStyleSheet'
,
file
=
foo2_file
,
title
=
''
,
precondition
=
''
,
content_type
=
'application/vnd.oasis.opendocument.text'
)
content_type
=
'application/vnd.oasis.opendocument.text'
)
if
custom
.
_getOb
(
'Foo3_getODTStyleSheet'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Foo3_getODTStyleSheet'
,
file
=
foo3_file
,
title
=
''
,
precondition
=
''
,
content_type
=
'application/vnd.oasis.opendocument.text'
)
content_type
=
'application/vnd.oasis.opendocument.text'
)
if
custom
.
_getOb
(
'Foo4_getODTStyleSheet'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Foo4_getODTStyleSheet'
,
file
=
foo4_file
,
title
=
''
,
precondition
=
''
,
content_type
=
'application/vnd.oasis.opendocument.text'
)
content_type
=
'application/vnd.oasis.opendocument.text'
)
if
custom
.
_getOb
(
'Foo5_getODTStyleSheet'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Foo5_getODTStyleSheet'
,
file
=
foo5_file
,
title
=
''
,
precondition
=
''
,
content_type
=
'application/vnd.oasis.opendocument.text'
)
content_type
=
'application/vnd.oasis.opendocument.text'
)
if
custom
.
_getOb
(
'Foo_getVariableODTStyleSheet'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Foo_getVariableODTStyleSheet'
,
file
=
variable_file_object
,
title
=
''
,
precondition
=
''
,
content_type
=
'application/vnd.oasis.opendocument.text'
)
erp5OOo
=
custom
.
manage_addProduct
[
'ERP5OOo'
]
...
...
product/ERP5OOo/tests/testOOoBatchMode.py
View file @
dfb15874
...
...
@@ -66,7 +66,7 @@ class TestOoodResponse(ERP5TypeTestCase):
custom
=
portal_skins
.
custom
addStyleSheet
=
custom
.
manage_addProduct
[
'OFSP'
].
manage_addFile
addStyleSheet
(
id
=
'Base_getODTStyleSheet'
,
file
=
import_file
,
title
=
''
,
precondition
=
''
,
content_type
=
'application/vnd.oasis.opendocument.text'
)
content_type
=
'application/vnd.oasis.opendocument.text'
)
addOOoTemplate
=
custom
.
manage_addProduct
[
'ERP5OOo'
].
addOOoTemplate
addOOoTemplate
(
id
=
'ERP5Site_viewNothingAsOdt'
,
title
=
''
)
portal_skins
.
changeSkin
(
skinname
=
None
)
...
...
product/ERP5OOo/tests/testOOoDynamicStyle.py
View file @
dfb15874
...
...
@@ -76,10 +76,10 @@ class TestOooDynamicStyle(ERP5TypeTestCase):
addStyleSheet
=
self
.
getPortal
().
manage_addProduct
[
'OFSP'
].
manage_addFile
if
getattr
(
self
.
getPortal
(),
'Test_getODTStyleSheet_en'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Test_getODTStyleSheet_en'
,
file
=
en_file
,
title
=
''
,
precondition
=
''
,
content_type
=
self
.
content_type_writer
)
content_type
=
self
.
content_type_writer
)
if
getattr
(
self
.
getPortal
(),
'Test_getODTStyleSheet_ja'
,
None
)
is
None
:
addStyleSheet
(
id
=
'Test_getODTStyleSheet_ja'
,
file
=
ja_file
,
title
=
''
,
precondition
=
''
,
content_type
=
self
.
content_type_writer
)
content_type
=
self
.
content_type_writer
)
if
getattr
(
self
.
getPortal
(),
'Base_getODTStyleSheetByLanguage'
,
None
)
is
None
:
script_body
=
"""
current_language = context.Localizer.get_selected_language()
...
...
product/ERP5Type/Base.py
View file @
dfb15874
...
...
@@ -81,7 +81,6 @@ from CopySupport import CopyContainer, CopyError,\
from
Errors
import
DeferredCatalogError
,
UnsupportedWorkflowMethod
from
Products.CMFActivity.ActiveObject
import
ActiveObject
from
Products.ERP5Type.Accessor.Accessor
import
Accessor
as
Method
from
Products.ERP5Type.Accessor.TypeDefinition
import
asDate
from
Products.ERP5Type.Message
import
Message
from
Products.ERP5Type.ConsistencyMessage
import
ConsistencyMessage
from
Products.ERP5Type.UnrestrictedMethod
import
UnrestrictedMethod
,
super_user
...
...
@@ -3229,9 +3228,8 @@ class Base(
if
history
and
'time'
in
history
[
0
])
except
ValueError
:
pass
if
getattr
(
aq_base
(
self
),
'CreationDate'
,
None
)
is
not
None
:
return
asDate
(
self
.
CreationDate
())
return
None
# JPS-XXX - try to find a way to return a creation date instead of None
if
getattr
(
aq_base
(
self
),
'creation_date'
,
None
):
return
self
.
creation_date
.
toZone
(
DateTime
().
timezone
())
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getModificationDate'
)
def
getModificationDate
(
self
):
...
...
@@ -3260,7 +3258,13 @@ class Base(
# Return a copy of history time, to prevent modification
return
DateTime
(
max_date
)
if
self
.
_p_serial
:
return
DateTime
(
TimeStamp
(
self
.
_p_serial
).
timeTime
())
return
DateTime
(
self
.
_p_mtime
)
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'modified'
)
def
modified
(
self
):
warnings
.
warn
(
'modified is a deprecated alias to getModificationDate.'
,
DeprecationWarning
)
return
self
.
getModificationDate
()
# Layout management
security
.
declareProtected
(
Permissions
.
AccessContentsInformation
,
'getApplicableLayout'
)
...
...
product/ERP5Type/ZopePatch.py
View file @
dfb15874
...
...
@@ -34,6 +34,7 @@ from Products.ERP5Type.patches import DCWorkflow
from
Products.ERP5Type.patches
import
Worklists
from
Products.ERP5Type.patches
import
BTreeFolder2
from
Products.ERP5Type.patches
import
WorkflowTool
from
Products.ERP5Type.patches
import
DynamicType
from
Products.ERP5Type.patches
import
XMLExportImport
from
Products.ERP5Type.patches
import
ppml
from
Products.ERP5Type.patches
import
Expression
...
...
product/ERP5Type/__init__.py
View file @
dfb15874
...
...
@@ -189,3 +189,18 @@ import zExceptions
ModuleSecurityInfo
(
'zExceptions'
).
declarePublic
(
*
filter
(
lambda
x
:
Exception
in
getattr
(
getattr
(
zExceptions
,
x
),
'__mro__'
,
()),
dir
(
zExceptions
)))
# BBB : allow load of fomer Products.CMFDefault.MembershipTool
# that has been replaced by Products.CMFCore.MembershipTool
try
:
from
Products.CMFDefault.MembershipTool
import
MembershipTool
except
ImportError
:
import
sys
,
imp
m
=
'Products.CMFDefault'
sys
.
modules
[
m
]
=
imp
.
new_module
(
m
)
m
+=
".MembershipTool"
sys
.
modules
[
m
]
=
m
=
imp
.
new_module
(
m
)
from
Products.CMFCore.MembershipTool
import
MembershipTool
m
.
MembershipTool
=
MembershipTool
del
m
product/ERP5Type/dynamic/portal_type_class.py
View file @
dfb15874
...
...
@@ -468,6 +468,15 @@ def synchronizeDynamicModules(context, force=False):
except
AttributeError
:
pass
# no Activity Tool yet
for
tool_id
in
(
"portal_properties"
,
"portal_uidannotation"
,
"portal_uidgenerator"
,
"portal_uidhandler"
):
if
portal
.
hasObject
(
tool_id
):
portal
.
_delObject
(
tool_id
,
suppress_events
=
True
)
migrate
=
True
if
tool_id
==
'portal_properties'
:
portal
.
portal_skins
.
erp5_xhtml_style
.
breadcrumbs
.
write
(
'return []'
)
if
migrate
:
portal
.
migrateToPortalTypeClass
()
portal
.
portal_skins
.
changeSkin
(
None
)
...
...
product/ERP5Type/patches/CMFCoreSkinnable.py
View file @
dfb15874
...
...
@@ -141,11 +141,9 @@ def CMFCoreSkinnableSkinnableObjectManager_changeSkin(self, skinname, REQUEST=No
Patched not to call getSkin.
'''
if
skinname
is
None
:
sfn
=
self
.
getSkinsFolderName
()
if
sfn
is
not
None
:
sf
=
getattr
(
self
,
sfn
,
None
)
if
sf
is
not
None
:
skinname
=
sf
.
getDefaultSkin
()
sf
=
getattr
(
self
,
"portal_skins"
,
None
)
if
sf
is
not
None
:
skinname
=
sf
.
getDefaultSkin
()
tid
=
get_ident
()
SKINDATA
[
tid
]
=
(
None
,
...
...
product/ERP5Type/patches/CMFCoreUtils.py
View file @
dfb15874
...
...
@@ -13,24 +13,25 @@
##############################################################################
from
Acquisition
import
aq_parent
from
Products.CMFCore.utils
import
getToolByName
,
SUBTEMPLATE
from
Products.CMFCore.utils
import
SUBTEMPLATE
from
zope.component
import
queryUtility
from
Products.CMFCore.interfaces
import
ICachingPolicyManager
# patch _setCacheHeaders so that existing headers are not overridden
def
_setCacheHeaders
(
obj
,
extra_context
):
"""Set cache headers according to cache policy manager for the obj."""
REQUEST
=
getattr
(
obj
,
'REQUEST'
,
None
)
if
REQUEST
is
not
None
:
call_count
=
getattr
(
REQUEST
,
SUBTEMPLATE
,
1
)
-
1
setattr
(
REQUEST
,
SUBTEMPLATE
,
call_count
)
if
call_count
!=
0
:
return
return
# cleanup
delattr
(
REQUEST
,
SUBTEMPLATE
)
content
=
aq_parent
(
obj
)
manager
=
getToolByName
(
obj
,
'caching_policy_manager'
,
None
)
manager
=
queryUtility
(
ICachingPolicyManager
)
if
manager
is
None
:
return
...
...
product/ERP5Type/patches/CookieCrumbler.py
View file @
dfb15874
...
...
@@ -30,6 +30,7 @@ from App.class_init import InitializeClass
from
Products.CMFCore.CookieCrumbler
import
CookieCrumbler
from
Products.CMFCore.CookieCrumbler
import
CookieCrumblerDisabled
from
urllib
import
quote
,
unquote
from
zExceptions
import
Redirect
from
ZPublisher.HTTPRequest
import
HTTPRequest
ATTEMPT_NONE
=
0
# No attempt at authentication
...
...
@@ -47,6 +48,10 @@ class PatchedCookieCrumbler(CookieCrumbler):
security
=
ClassSecurityInfo
()
CookieCrumbler
.
auto_login_page
=
'login_form'
CookieCrumbler
.
unauth_page
=
''
CookieCrumbler
.
logout_page
=
'logged_out'
def
getLoginURL
(
self
):
'''
Redirects to the login page.
...
...
@@ -176,14 +181,175 @@ def modifyRequest(self, req, resp):
CookieCrumbler
.
modifyRequest
=
modifyRequest
def
credentialsChanged
(
self
,
user
,
name
,
pw
):
ac
=
standard_b64encode
(
'%s:%s'
%
(
name
,
pw
))
method
=
self
.
getCookieMethod
(
'setAuthCookie'
,
self
.
defaultSetAuthCookie
)
resp
=
self
.
REQUEST
[
'RESPONSE'
]
method
(
resp
,
self
.
auth_cookie
,
quote
(
ac
)
)
def
credentialsChanged
(
self
,
user
,
name
,
pw
,
request
=
None
):
"""
Updates cookie credentials if user details are changed.
"""
if
request
is
None
:
request
=
getRequest
()
# BBB for Membershiptool
reponse
=
request
[
'RESPONSE'
]
# <patch>
# We don't want new lines, so use base64.standard_b64encode instead of
# base64.encodestring
ac
=
standard_b64encode
(
'%s:%s'
%
(
name
,
pw
)).
rstrip
()
# </patch>
method
=
self
.
getCookieMethod
(
'setAuthCookie'
,
self
.
defaultSetAuthCookie
)
method
(
reponse
,
self
.
auth_cookie
,
quote
(
ac
))
CookieCrumbler
.
credentialsChanged
=
credentialsChanged
# The following patches are to keep the original behaviour of automatic
# redirection to login page. Recent CMF uses a view that is implemented
# in CMFDefault (UnauthorizedView, on zExceptions.Unauthorized).
class
ResponseCleanup
:
def
__init__
(
self
,
resp
):
self
.
resp
=
resp
def
__del__
(
self
):
# Free the references.
#
# No errors of any sort may propagate, and we don't care *what*
# they are, even to log them.
try
:
del
self
.
resp
.
unauthorized
except
Exception
:
pass
try
:
del
self
.
resp
.
_unauthorized
except
Exception
:
pass
try
:
del
self
.
resp
except
Exception
:
pass
if
1
:
def
__call__
(
self
,
container
,
req
):
'''The __before_publishing_traverse__ hook.'''
resp
=
req
[
'RESPONSE'
]
try
:
attempt
=
self
.
modifyRequest
(
req
,
resp
)
except
CookieCrumblerDisabled
:
return
# <patch>
if
req
.
get
(
'disable_cookie_login__'
,
0
):
return
if
(
self
.
unauth_page
or
attempt
==
ATTEMPT_LOGIN
or
attempt
==
ATTEMPT_NONE
):
# Modify the "unauthorized" response.
req
.
_hold
(
ResponseCleanup
(
resp
))
resp
.
unauthorized
=
self
.
unauthorized
resp
.
_unauthorized
=
self
.
_unauthorized
# </patch>
if
attempt
!=
ATTEMPT_NONE
:
# Trying to log in or resume a session
if
self
.
cache_header_value
:
# we don't want caches to cache the resulting page
resp
.
setHeader
(
'Cache-Control'
,
self
.
cache_header_value
)
# demystify this in the response.
resp
.
setHeader
(
'X-Cache-Control-Hdr-Modified-By'
,
'CookieCrumbler'
)
phys_path
=
self
.
getPhysicalPath
()
# <patch>
if
self
.
logout_page
:
# Cookies are in use.
page
=
getattr
(
container
,
self
.
logout_page
,
None
)
if
page
is
not
None
:
# Provide a logout page.
req
.
_logout_path
=
phys_path
+
(
'logout'
,)
req
.
_credentials_changed_path
=
(
phys_path
+
(
'credentialsChanged'
,))
# </patch>
def
_cleanupResponse
(
self
):
# XXX: this method violates the rules for tools/utilities:
# it depends on self.REQUEST
resp
=
self
.
REQUEST
[
'RESPONSE'
]
# No errors of any sort may propagate, and we don't care *what*
# they are, even to log them.
try
:
del
resp
.
unauthorized
except
Exception
:
pass
try
:
del
resp
.
_unauthorized
except
Exception
:
pass
return
resp
security
.
declarePrivate
(
'unauthorized'
)
def
unauthorized
(
self
):
resp
=
self
.
_cleanupResponse
()
# If we set the auth cookie before, delete it now.
if
resp
.
cookies
.
has_key
(
self
.
auth_cookie
):
del
resp
.
cookies
[
self
.
auth_cookie
]
# Redirect if desired.
url
=
self
.
getUnauthorizedURL
()
if
url
is
not
None
:
raise
Redirect
,
url
# Fall through to the standard unauthorized() call.
resp
.
unauthorized
()
def
_unauthorized
(
self
):
resp
=
self
.
_cleanupResponse
()
# If we set the auth cookie before, delete it now.
if
resp
.
cookies
.
has_key
(
self
.
auth_cookie
):
del
resp
.
cookies
[
self
.
auth_cookie
]
# Redirect if desired.
url
=
self
.
getUnauthorizedURL
()
if
url
is
not
None
:
resp
.
redirect
(
url
,
lock
=
1
)
# We don't need to raise an exception.
return
# Fall through to the standard _unauthorized() call.
resp
.
_unauthorized
()
security
.
declarePublic
(
'getUnauthorizedURL'
)
def
getUnauthorizedURL
(
self
):
'''
Redirects to the login page.
'''
# XXX: this method violates the rules for tools/utilities:
# it depends on self.REQUEST
req
=
self
.
REQUEST
resp
=
req
[
'RESPONSE'
]
attempt
=
getattr
(
req
,
'_cookie_auth'
,
ATTEMPT_NONE
)
if
attempt
==
ATTEMPT_NONE
:
# An anonymous user was denied access to something.
page_id
=
self
.
auto_login_page
retry
=
''
elif
attempt
==
ATTEMPT_LOGIN
:
# The login attempt failed. Try again.
page_id
=
self
.
auto_login_page
retry
=
'1'
else
:
# An authenticated user was denied access to something.
page_id
=
self
.
unauth_page
retry
=
''
if
page_id
:
page
=
self
.
restrictedTraverse
(
page_id
,
None
)
if
page
is
not
None
:
came_from
=
req
.
get
(
'came_from'
,
None
)
if
came_from
is
None
:
came_from
=
req
.
get
(
'ACTUAL_URL'
)
query
=
req
.
get
(
'QUERY_STRING'
)
if
query
:
# Include the query string in came_from
if
not
query
.
startswith
(
'?'
):
query
=
'?'
+
query
came_from
=
came_from
+
query
url
=
'%s?came_from=%s&retry=%s&disable_cookie_login__=1'
%
(
page
.
absolute_url
(),
quote
(
came_from
),
retry
)
return
url
return
None
CookieCrumbler
.
__call__
=
__call__
CookieCrumbler
.
_cleanupResponse
=
_cleanupResponse
CookieCrumbler
.
unauthorized
=
unauthorized
CookieCrumbler
.
_unauthorized
=
_unauthorized
CookieCrumbler
.
getUnauthorizedURL
=
getUnauthorizedURL
###
CookieCrumbler
.
security
=
security
InitializeClass
(
CookieCrumbler
)
product/ERP5Type/patches/DynamicType.py
0 → 100644
View file @
dfb15874
##############################################################################
#
# Copyright (c) 2001 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from
Products.CMFCore.DynamicType
import
DynamicType
def
getTypeInfo
(
self
):
""" Get the TypeInformation object specified by the portal type.
"""
# <patch>
tool
=
getattr
(
self
.
getPortalObject
(),
"portal_types"
,
None
)
# </patch>
if
tool
is
None
:
return
None
return
tool
.
getTypeInfo
(
self
)
# Can return None.
DynamicType
.
getTypeInfo
=
getTypeInfo
product/ERP5Type/patches/Restricted.py
View file @
dfb15874
...
...
@@ -265,7 +265,9 @@ allow_module('cStringIO')
import
cStringIO
allow_type
(
cStringIO
.
InputType
)
allow_type
(
cStringIO
.
OutputType
)
allow_module
(
'io'
)
import
io
allow_type
(
io
.
BytesIO
)
ModuleSecurityInfo
(
'cgi'
).
declarePublic
(
'escape'
,
'parse_header'
)
allow_module
(
'datetime'
)
...
...
product/ERP5Type/patches/WorkflowTool.py
View file @
dfb15874
...
...
@@ -951,4 +951,17 @@ def canDoActionFor(self, ob, action, wf_id=None, guard_kw={}):
WorkflowTool
.
canDoActionFor
=
canDoActionFor
security
.
declarePrivate
(
'_listTypeInfo'
)
def
_listTypeInfo
(
self
):
""" List the portal types which are available.
"""
# <patch>
ttool
=
getattr
(
self
.
getPortalObject
(),
"portal_types"
,
None
)
# </patch>
if
ttool
is
not
None
:
return
ttool
.
listTypeInfo
()
return
()
WorkflowTool
.
_listTypeInfo
=
_listTypeInfo
InitializeClass
(
WorkflowTool
)
product/ERP5Type/tests/ERP5TypeTestCase.py
View file @
dfb15874
...
...
@@ -839,6 +839,10 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase):
PAS
.
_extractUserIds
=
orig_extractUserIds
# Restore security manager
setSecurityManager
(
sm
)
# Restore site removed by closing of request
setSite
(
self
.
portal
)
# Make sure that the skin cache does not have objects that were
# loaded with the connection used by the requested url.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment