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
Labels
Merge Requests
138
Merge Requests
138
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
Jobs
Commits
Open sidebar
nexedi
erp5
Commits
a72c1dd8
Commit
a72c1dd8
authored
Dec 04, 2020
by
Nicolas Wavrant
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
TrashTool: add function to restore objects
parent
eab00f14
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
124 additions
and
0 deletions
+124
-0
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testTrashTool.py
...TemplateItem/portal_components/test.erp5.testTrashTool.py
+50
-0
product/ERP5/Tool/TrashTool.py
product/ERP5/Tool/TrashTool.py
+74
-0
No files found.
bt5/erp5_core_test/TestTemplateItem/portal_components/test.erp5.testTrashTool.py
View file @
a72c1dd8
...
@@ -355,6 +355,32 @@ class TestTrashTool(ERP5TypeTestCase):
...
@@ -355,6 +355,32 @@ class TestTrashTool(ERP5TypeTestCase):
self
.
assertTrue
(
subcat
is
not
None
)
self
.
assertTrue
(
subcat
is
not
None
)
sequence
.
edit
(
subcat_path
=
subcat
.
getPath
())
sequence
.
edit
(
subcat_path
=
subcat
.
getPath
())
def
stepDeleteBaseCategory
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
pc
=
self
.
getCategoryTool
()
pc
.
manage_delObjects
(
ids
=
[
sequence
.
get
(
'bc_id'
)])
def
stepRestore
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
trash_id
=
sequence
.
get
(
'trash_id'
)
trash
=
self
.
getTrashTool
()
trashbin
=
trash
.
_getOb
(
trash_id
,
None
)
bc_id
=
sequence
.
get
(
'bc_id'
)
trash
.
restoreObject
(
trashbin
,
[
'portal_categories_items'
],
bc_id
)
def
stepCheckRestore
(
self
,
sequence
=
None
,
sequence_list
=
None
,
**
kw
):
bc_id
=
sequence
.
get
(
'bc_id'
)
bc
=
self
.
portal
.
portal_categories
[
bc_id
]
self
.
assertTrue
(
sorted
(
bc
.
objectIds
())
==
sorted
(
sequence
.
get
(
'category_id_list'
))
)
self
.
assertEqual
(
len
(
self
.
portal
.
portal_catalog
(
portal_type
=
'Category'
,
parent_uid
=
bc
.
getUid
()
)
),
10
)
# tests
# tests
def
test_01_checkTrashBinCreation
(
self
,
quiet
=
quiet
,
run
=
run_all_test
):
def
test_01_checkTrashBinCreation
(
self
,
quiet
=
quiet
,
run
=
run_all_test
):
if
not
run
:
return
if
not
run
:
return
...
@@ -477,6 +503,30 @@ class TestTrashTool(ERP5TypeTestCase):
...
@@ -477,6 +503,30 @@ class TestTrashTool(ERP5TypeTestCase):
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
,
quiet
=
quiet
)
sequence_list
.
play
(
self
,
quiet
=
quiet
)
def
test_07_checkRestore
(
self
,
quiet
=
quiet
,
run
=
run_all_test
):
if
not
run
:
return
if
not
quiet
:
message
=
'Test Check Backup Without Subobjects'
ZopeTestCase
.
_print
(
'
\
n
%s '
%
message
)
LOG
(
'Testing... '
,
0
,
message
)
sequence_list
=
SequenceList
()
sequence_string
=
'
\
CheckTrashToolExists
\
CreateTrashBin
\
AddBaseCategory
\
AddCategories
\
Tic
\
BackupObjectsWithKeepingSubobjects
\
Tic
\
CheckObjectBackupWithSubObjects
\
DeleteBaseCategory
\
Tic
\
Restore
\
Tic
\
CheckRestore
\
'
sequence_list
.
addSequenceString
(
sequence_string
)
sequence_list
.
play
(
self
,
quiet
=
quiet
)
def
test_suite
():
def
test_suite
():
...
...
product/ERP5/Tool/TrashTool.py
View file @
a72c1dd8
...
@@ -34,6 +34,7 @@ from Products.ERP5Type.Globals import InitializeClass, DTMLFile
...
@@ -34,6 +34,7 @@ from Products.ERP5Type.Globals import InitializeClass, DTMLFile
from
Products.ERP5Type.Tool.BaseTool
import
BaseTool
from
Products.ERP5Type.Tool.BaseTool
import
BaseTool
from
Products.ERP5Type
import
Permissions
from
Products.ERP5Type
import
Permissions
from
Products.ERP5
import
_dtmldir
from
Products.ERP5
import
_dtmldir
from
zExceptions
import
BadRequest
from
zLOG
import
LOG
,
WARNING
from
zLOG
import
LOG
,
WARNING
from
DateTime
import
DateTime
from
DateTime
import
DateTime
from
Acquisition
import
aq_base
from
Acquisition
import
aq_base
...
@@ -189,6 +190,79 @@ class TrashTool(BaseTool):
...
@@ -189,6 +190,79 @@ class TrashTool(BaseTool):
)
)
return
trashbin
return
trashbin
security
.
declarePrivate
(
'restoreObject'
)
def
restoreObject
(
self
,
trashbin
,
container_path
,
object_id
,
pass_if_exist
=
True
):
"""
Restore an object from the trash bin (copy it under portal)
"""
portal
=
self
.
getPortalObject
()
# recreate path of the backup object if necessary
backup_object_container
=
portal
for
path
in
container_path
:
if
path
.
endswith
(
'_items'
):
path
=
path
[
0
:
-
len
(
'_items'
)]
if
path
not
in
backup_object_container
.
objectIds
():
if
not
hasattr
(
aq_base
(
backup_object_container
),
"newContent"
):
backup_object_container
.
manage_addFolder
(
id
=
path
,)
backup_object_container
=
backup_object_container
.
_getOb
(
path
)
else
:
backup_object_container
=
backup_object_container
.
newContent
(
portal_type
=
'Folder'
,
id
=
path
,
)
else
:
backup_object_container
=
backup_object_container
.
_getOb
(
path
)
# backup the object
# here we choose export/import to copy because cut/paste
# do too many things and check for what we want to do
object_path
=
container_path
+
[
object_id
]
obj
=
trashbin
.
restrictedTraverse
(
object_path
,
None
)
if
obj
is
not
None
:
connection
=
obj
.
_p_jar
o
=
obj
while
connection
is
None
:
o
=
o
.
aq_parent
connection
=
o
.
_p_jar
if
obj
.
_p_oid
is
None
:
LOG
(
"Trash Tool backupObject"
,
WARNING
,
"Trying to backup uncommitted object %s"
%
object_path
)
return
{}
if
isinstance
(
obj
,
Broken
):
LOG
(
"Trash Tool backupObject"
,
WARNING
,
"Can't backup broken object %s"
%
object_path
)
klass
=
obj
.
__class__
if
klass
.
__module__
[:
27
]
in
(
'Products.ERP5Type.Document.'
,
'erp5.portal_type'
):
# meta_type is required so that a broken object
# can be removed properly from a BTreeFolder2
# (unfortunately, we can only guess it)
klass
.
meta_type
=
'ERP5'
+
re
.
subn
(
'(?=[A-Z])'
,
' '
,
klass
.
__name__
)[
0
]
return
copy
=
connection
.
exportFile
(
obj
.
_p_oid
)
# import object in trash
connection
=
backup_object_container
.
_p_jar
o
=
backup_object_container
while
connection
is
None
:
o
=
o
.
aq_parent
connection
=
o
.
_p_jar
copy
.
seek
(
0
)
try
:
backup
=
connection
.
importFile
(
copy
)
if
hasattr
(
aq_base
(
backup
),
'isIndexable'
):
del
backup
.
isIndexable
backup_object_container
.
_setObject
(
object_id
,
backup
)
except
(
AttributeError
,
ImportError
):
# XXX we can go here due to formulator because attribute
# field_added doesn't not exists on parent if it is a Trash
# Folder and not a Form, or a module for the old object is
# already removed, and we cannot backup the object
LOG
(
"Trash Tool backupObject"
,
WARNING
,
"Can't backup object %s"
%
object_path
)
except
BadRequest
:
if
pass_if_exist
:
pass
security
.
declareProtected
(
Permissions
.
ManagePortal
,
'getTrashBinObjectsList'
)
security
.
declareProtected
(
Permissions
.
ManagePortal
,
'getTrashBinObjectsList'
)
def
getTrashBinObjectsList
(
self
,
trashbin
):
def
getTrashBinObjectsList
(
self
,
trashbin
):
"""
"""
...
...
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