| 1 | ## Controller Python Script "folder_publish" |
|---|
| 2 | ##bind container=container |
|---|
| 3 | ##bind context=context |
|---|
| 4 | ##bind namespace= |
|---|
| 5 | ##bind script=script |
|---|
| 6 | ##bind state=state |
|---|
| 7 | ##bind subpath=traverse_subpath |
|---|
| 8 | ##parameters=workflow_action=None, paths=[], comment='No comment', expiration_date=None, effective_date=None, include_children=False, recurse_level=0 |
|---|
| 9 | ##title=Publish objects from a folder |
|---|
| 10 | ## |
|---|
| 11 | |
|---|
| 12 | from ZODB.POSException import ConflictError |
|---|
| 13 | from Products.CMFPlone.utils import transaction_note |
|---|
| 14 | from Products.CMFPlone import PloneMessageFactory as _ |
|---|
| 15 | |
|---|
| 16 | plone_utils=context.plone_utils |
|---|
| 17 | REQUEST=context.REQUEST |
|---|
| 18 | workflow = context.portal_workflow |
|---|
| 19 | content_status_modify=context.content_status_modify |
|---|
| 20 | failed = {} |
|---|
| 21 | success = {} |
|---|
| 22 | |
|---|
| 23 | if workflow_action is None: |
|---|
| 24 | context.plone_utils.addPortalMessage(_(u'You must select a publishing action.'), 'error') |
|---|
| 25 | return state.set(status='failure') |
|---|
| 26 | if not paths: |
|---|
| 27 | context.plone_utils.addPortalMessage(_(u'You must select content to change.'), 'error') |
|---|
| 28 | return state.set(status='failure') |
|---|
| 29 | |
|---|
| 30 | objs = context.getObjectsFromPathList(paths) |
|---|
| 31 | |
|---|
| 32 | for o in objs: |
|---|
| 33 | obj_path = '/'.join(o.getPhysicalPath()) |
|---|
| 34 | try: |
|---|
| 35 | if o.isPrincipiaFolderish and include_children: |
|---|
| 36 | |
|---|
| 37 | # call the script to do the workflow action |
|---|
| 38 | # catch it if there is not workflow action for this object |
|---|
| 39 | # but continue with subobjects. |
|---|
| 40 | # Since we can have mixed portal_type objects it can occur |
|---|
| 41 | # quite easily that the workflow_action doesn't work for some objects |
|---|
| 42 | # but we need to keep on going. |
|---|
| 43 | try: |
|---|
| 44 | o.content_status_modify( workflow_action, |
|---|
| 45 | comment, |
|---|
| 46 | effective_date=effective_date, |
|---|
| 47 | expiration_date=expiration_date, |
|---|
| 48 | bulkChange=True) |
|---|
| 49 | |
|---|
| 50 | |
|---|
| 51 | except ConflictError: |
|---|
| 52 | raise |
|---|
| 53 | except Exception, e: |
|---|
| 54 | # skip this object but continue with sub-objects. |
|---|
| 55 | failed[obj_path]=e |
|---|
| 56 | |
|---|
| 57 | subobject_paths = ["%s/%s" % ('/'.join(o.getPhysicalPath()), id) for id in o.objectIds()] |
|---|
| 58 | # Only call folder_publish on non empty folders |
|---|
| 59 | if subobject_paths: |
|---|
| 60 | o.folder_publish( workflow_action, |
|---|
| 61 | subobject_paths, |
|---|
| 62 | comment=comment, |
|---|
| 63 | include_children=include_children, |
|---|
| 64 | effective_date=effective_date, |
|---|
| 65 | expiration_date=expiration_date, |
|---|
| 66 | recurse_level=recurse_level + 1) |
|---|
| 67 | else: |
|---|
| 68 | o.content_status_modify( workflow_action, |
|---|
| 69 | comment, |
|---|
| 70 | effective_date=effective_date, |
|---|
| 71 | expiration_date=expiration_date, |
|---|
| 72 | bulkChange=True) |
|---|
| 73 | |
|---|
| 74 | |
|---|
| 75 | success[obj_path]=comment |
|---|
| 76 | except ConflictError: |
|---|
| 77 | raise |
|---|
| 78 | except Exception, e: |
|---|
| 79 | failed[obj_path]=e |
|---|
| 80 | |
|---|
| 81 | if recurse_level == 0: |
|---|
| 82 | context.restrictedTraverse('search_view').changeStateEvent(context, workflow_action, bulkChange=True, initial_state=None) |
|---|
| 83 | |
|---|
| 84 | transaction_note( str(paths) + ' transitioned ' + workflow_action ) |
|---|
| 85 | |
|---|
| 86 | # It is necessary to set the context to override context from content_status_modify |
|---|
| 87 | context.plone_utils.addPortalMessage(_(u'Item state changed.')) |
|---|
| 88 | return state.set(context=context) |
|---|