[CMF-checkins] CVS: CMF - update_discussion.py:1.1

tseaver@digicool.com tseaver@digicool.com
Thu, 14 Jun 2001 16:27:47 -0400 (EDT)


Update of /cvs-repository/CMF/CMFDefault/Extensions
In directory korak.digicool.com:/tmp/cvs-serv30518/Extensions

Added Files:
	update_discussion.py 
Log Message:



  - Adds a set of baseline unit tests for the discussions
    machinery, including tests for:

    o policy checks (whether discussions are allowable)

    o nested replies

    o cataloguing of replies

    o propagation of 'manage_beforeDelete' from the host content
      object, and correct un-cataloguing.

  - Cleans up a lot of cruft, including fossilized inheritance,
    old-style security declarations, etc., in
    CMFDefault.DiscussionItem.  In particular, DiscussionItem
    now implements the DiscussionResponse interface directly,
    instead of mixing in the older implementation.

  - Replaces the current "path-based" 'in_reply_to' with a simpler,
    more robust scheme.
    
    o The old version was a legacy of the much older usage, which
      had discussion items in users' "Correspondence" folders, and
      assembled them into threads using catalog queries;  it was
      fragile in the face of moves or renames of the "host"
      content object.

    o The new scheme stores 'None' in the 'in_reply_to' field to
      indicate that the item is a "top-level" reply to the host
      content object, or the simple ID of the sibling, for
      threaded replies.

  - Refactors the skins for discussions a bit, moving the "above
    in thread" logic into a separate method, and adding a special
    view for DiscussionItems which uses it.

  - Adds an 'upgrade_discussion' ExternalMethod to CMFDefault;
    this method:

     1. Installs (if one isn't already there) a
        FactoryTypeInformation object for DiscussionItems.  This
        FTI is "crippled" for adding objects (no factory/product),
        but provides a hook on which to hang the custom view, and
        set other type-specific policies.

     2. Removes the "(default)" workflow for DiscussionItems, so
        as not to present the "Retract", etc. actions;  later, we
        might add a special workflow, to permit sufficiently
        privileged users to delete replies.

     3. Updates existing DiscussionItems to conform to the new
        scheme.



--- Added File update_discussion.py in package CMF ---
import string

from Products.CMFCore.TypesTool import FactoryTypeInformation
from Products.CMFDefault import DiscussionItem

def update_discussion( self, split=string.split ):
    """
     1. Install (if it isn't there already) a type information
        object for DiscussionItems, so that they can get actions,
        etc.  Erase the "(default)" workflow bound to it, to prevent
        showing the "Retract" options, etc.

     2. Update all DiscussionItems to use the new marking for
        'in_reply_to':

          - Items which are replies to the containing content object
            have None as their 'in_reply_to';

          - Items which are replies to sibling items have the sibling's
            ID as their 'in_reply_to'.
        
        The representation we are converting from was:

          - Items which are replies to the containing content object
            have the portal-relative pathstring of the content object
            as their 'in_reply_to';

          - Items which are replies to sibling items have the absolute
            path of the sibling as their 'in_reply_to'.
    """

    log = []
    a = log.append
    types_tool = self.portal_types
    if not getattr( types_tool, 'Discussion Item', None ):

        fti = apply( FactoryTypeInformation
                   , ()
                   , DiscussionItem.factory_type_information[0]
                   )
        types_tool._setObject( 'Discussion Item', fti )
        a( 'Added type object for DiscussionItem' )

        workflow_tool = self.portal_workflow
        workflow_tool.setChainForPortalTypes( ( 'Discussion Item', ), () )
        a( 'Erased workflow for DiscussionItem' )

    items = self.portal_catalog.searchResults( meta_type='Discussion Item' )
    a( 'DiscussionItems updated:' )

    for item in items:

        object = item.getObject()
        talkback = object.aq_parent
        path = item.getPath()
        in_reply_to = object.in_reply_to
        
        if in_reply_to is None: # we've been here already
            continue

        irt_elements = split( in_reply_to, '/' )

        if len( irt_elements ) == 1:
            if talkback._container.get( irt_elements[0] ):
                # we've been here already
                continue

        if irt_elements[0] == '': # absolute, so we are IRT a sibling
            sibling_id = irt_elements[ -1 ]
            if talkback._container.get( sibling_id, None ):
                in_reply_to = sibling_id
            else:
                in_reply_to = None
        else:
            in_reply_to = None

        object.in_reply_to = in_reply_to
        assert object.inReplyTo() # sanity check
        object.reindexObject()

        a( path )
    
    return string.join( log, '\n' )