Matthew Trevor
Matthew Trevor

Reputation: 14961

New & renamed workflows with existing content

I have a site with a custom content type Content, which initially had a single workflow attached, content_workflow. There are several thousand existing instances of Content.

I now have a need to add a second workflow to this type, content_beta_workflow. How can I update all existing content to be part of the new workflow?

On a related note: if I want rename the initial workflow to content_alpha_workflow, how can I update all existing content to reflect this change?

Upvotes: 1

Views: 242

Answers (2)

cewing
cewing

Reputation: 2248

If you are simply changing from one workflow to the other, follow these steps:

  1. Go to Site Setup > Types
  2. Select your custom content type from the drop down menu, the page will update to display the current workflow
  3. Select your new workflow from the dropdown, a map will be generated showing each state in the current workflow
  4. For each state, select the state in your new workflow that most closely matches (or is most appropriate)

When you save, all objects of your custom site will be updated to use the new workflow. For each state in the map from the original workflow, existing content in that state will be put into the state you chose in step 4 above. Security settings will be re-indexed and you are done.

As for renaming the old workflow, you can do so in the portal_workflow tool in the ZMI. But only change the human-facing Title of the workflow. Changing the ID may have side effects for the workflow history of your content.

edited

Okay, I see from your comment that you are looking to add a new workflow to a type in addition to the one it already has. Here's a bit of sample code to accomplish that:

my_type = 'Content' # This is your content portal_type name
my_wf = 'content_workflow_beta'
wf_chain = list(wf_tool.getChainForPortalType(my_type))
if my_wf not in wf_chain:
    wf_chain.append(my_wf)
wf_tool.setChainForPortalTypes([my_type], wf_chain)

You can add this code in an upgrade step for the package that defines your content type and workflows. Add a call to updateRoleMappings on the workflow tool and you'll be set to use the new workflow through the standard Plone UI in addition to your original workflow.

As you've already found, you can also manually update the workflow history of all objects to rename workflow ID, but that's a pretty invasive step.

Upvotes: 0

Matthew Trevor
Matthew Trevor

Reputation: 14961

As workflow_history is a dict property on each content item, it was a case of adding or updating suitable items as required. First, I copied the GenericSetup for content_workflow to content_alpha_workflow. Next, I created content_beta_workflow and added it to the profile. Then I wrote the following upgrade step:

import logging
from DateTime import DateTime

def modify_content_workflow_history(context, logger=None):
    if logger is None: logger = logging.getLogger('my.product')

    # import the new workflows
    context.portal_setup.runImportStepFromProfile('profile-my.product:default', 'workflow')

    # set up some defaults for the new records
    _history_defaults = dict(
        action = None,
        actor = 'admin',
        comments = 'automatically created by update v2',
        time = DateTime(),        
    )
    _alpha_defaults = dict(review_state = 'alpha_state_1', **_history_defaults)
    _beta_defaults = dict(review_state = 'beta_state_1', **_history_defaults)

    for parent in context.parents.values():
        for content in parent.content.values():

            # don't acquire the parent's history
            if 'parent_workflow' in content.workflow_history:
                content.workflow_history = {}

            # copy content_workflow to content_alpha_workflow
            if 'content_workflow' in content.workflow_history:
                alpha_defaults = context.workflow_history['content_workflow']
                del content.workflow_history['content_workflow']
            else:
                alpha_defaults = (_alpha_defaults,) # must be a tuple
            content.workflow_history['ctcc_content_alpha_workflow'] = alpha_defaults

            # create the beta workflow with a modified actor
            beta_defaults = dict(**_beta_defaults)
            beta_defaults['actor'] = u'%suser' % parent.id
            content.workflow_history['ctcc_content_beta_workflow'] = (beta_defaults,)

    logger.info('Content workflow history updated')

Upvotes: 0

Related Questions