Logo Search packages:      
Sourcecode: zope-cmfpgforum version File versions

CMFpgForum.py

##############################################################################
#
# Copyright (c) 2003 - Emergence by Design Inc. - All Rights Reserved
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,  USA.
#
##############################################################################

import os, urllib, sql, string, urllib
from string import upper
from Globals import InitializeClass, HTMLFile, ImageFile, MessageDialog
from App.Common import package_home
from DocumentTemplate import DT_Var
from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
from Products.CMFCore.PortalContent import PortalContent
from Products.CMFCore.WorkflowCore import WorkflowAction
from Products.CMFCore.utils import getToolByName
from Products.CMFCore.TypesTool import ContentFactoryMetadata

# Import permission names
from Products.CMFCore import CMFCorePermissions
from AccessControl import ClassSecurityInfo, Permissions, SecurityManagement

type_id = 'CMF pg Forum'
meta_type = 'CMF pg Forum'
factory_type_information = {'id': type_id,
     'meta_type': 'CMF pg Forum',
     'description': ('A forum hold postings by users of the website, as well as replies to postings and other replies. Postings are searchable. This forum object needs a PostGreSQL backend. Please ensure a PostGreSQL database object is created inside this CMF site.'),
     'product': 'CMFpgForum',
     'factory': 'addCMFpgForum',
     'immediate_view': 'message_board_edit_form',
     'actions': ({'id': 'view',
                  'name': 'View',
                  'action': 'message_board_view',
                  'permissions': (CMFCorePermissions.View,)},
                 {'id': 'edit',
                  'name': 'Edit',
                  'action': 'message_board_edit_form',
                  'permissions': (CMFCorePermissions.ManageProperties,)},
                 {'id': 'delete',
                  'name': 'Delete',
                  'action': 'manage_suicide',
                  'permissions': (Permissions.delete_objects,)},
                 ),
     }

def registerCMFpgForum(self):
    """Register the CMFpgForum as a new portal type"""
    try:
        typestool = getToolByName(self, 'portal_types')
    except:
        # we're not inside a cmf site
        return MessageDialog(
               title  ='CMF site not found',
               message="You can only register '%s' under a CMF site. Please go to a CMF site and register again." % meta_type,
               action ='manage_main')

    if type_id in typestool.objectIds():
        return MessageDialog(
               title  ="'%s' registered" % meta_type,
               message="A portal type '%s' is already registered to this CMF site." % meta_type,
               action ='manage_main')
    else:
        cfm = apply(ContentFactoryMetadata, (), factory_type_information)
        typestool._setObject(type_id, cfm)
        return MessageDialog(
               title  ="'%s'registered" % meta_type,
               message="A new portal type '%s' is registered to this CMF site." % meta_type,
               action ='manage_main')



def addCMFpgForum(self, id, REQUEST=None):
    """Create an new CMFpgForum"""
    if self.SQLConnectionIDs() == []:
        return MessageDialog(
               title  ="Failed to create instance of '%s'" % meta_type,
               message="Unable to find any database connection object in this CMF site.",
               action ='.')
    else:
        self._setObject(id, CMFpgForum(id))

00095 class CMFpgForum(PortalContent, DefaultDublinCoreImpl, sql.SQLMethods):
    """ """

    meta_type = meta_type

    security = ClassSecurityInfo()
    security.declareObjectPublic()

00103     def __init__(self, id):
        """Initialize an instance of the class"""
        DefaultDublinCoreImpl.__init__(self)
        self.id=id
        self.connection_id = None # the id of the connectin object

    def url_quote(self, v):
        return urllib.quote(v)

    def get_parent_info(self):
        ret = {}

        try:
          ret['nav_location'] = self.restrictedTraverse(self.getPhysicalPath()[-2]).nav_location
        except:
          ret['nav_location'] = ''

        try:
          ret['title'] = self.restrictedTraverse(self.getPhysicalPath()[-2]).title
        except:
          ret['title'] = ''

        try:
          ret['type'] = self.restrictedTraverse(self.getPhysicalPath()[-2]).meta_type
        except:
          ret['type'] = ''

        return ret

    def isJustAdded(self):
        # return true is an instance of CMFpgForum is added
        return self.connection_id is None

    def message_board_edit (self, id, title, description, connection_id='', sort_order='', nav_location=''):
        "  "
        REQUEST = self.REQUEST

        if title == self.title == '' :
            return MessageDialog(
                   title = "Missing title",
                   message="The value of title is empty. Please specify one.",
                   action ='message_board_edit_form')

        if self.isJustAdded():
            # just added
            self.connection_id = connection_id
            # try to create tables
            try:
                self.sqlCreateTables()
            except Exception, msg:
                msge = ''.join(msg.args)
                if msge.find('already exists') > 0:
                    # already created
                    pass
                else:
                    raise Exception, msg

            self.MESSAGE_BOARD_ID = self.getNextval_MESSAGE_BOARD_ID_SEQ()[0][0]

        id=id.strip()
        if id != self.getId():
            try:
                self.getParentNode().manage_renameObject(self.getId(), id)
            except: #XXX have to do this for Topics and maybe other folderish objects
                self.aq_parent.manage_renameObject(obj.getId(), id)

        if self.hasProperty('nav_location'):
                self.manage_changeProperties(nav_location=nav_location)
        else:
                self.manage_addProperty('nav_location',nav_location,'string')

        self.editMetadata(title=title, description=description)

        qst='?portal_status_message=Folder+changed.'

        distinct_sort_order_list = []
        this_nav_location = nav_location

        if self.isUnderZoil():
            if self.hasProperty('sort_order'):
                    self.manage_changeProperties(sort_order=sort_order)
            else:
                    self.manage_addProperty('sort_order',sort_order,'int')

            for sibling in self.restrictedTraverse(self.getPhysicalPath()[len(self.getPhysicalPath())-2]).objectValues(['Document','Skinned Folder']):
                if not sibling.getId() == self.getId():
                    if str(sibling.nav_location) == str(this_nav_location):
                        if not int(sibling.sort_order) in distinct_sort_order_list:
                            distinct_sort_order_list.append(int(sibling.sort_order))

        if sort_order and int(sort_order) in distinct_sort_order_list:
            REQUEST.RESPONSE.redirect( self.absolute_url() + '/folder_edit_sort_order' + qst)
        else:
            REQUEST.RESPONSE.redirect( self.absolute_url() + '/message_board_view' + qst)


    def isUnderZoil(self):
        return hasattr(self, 'folder_edit_sort_order')

    def thread_add_action (self, MESSAGE_BOARD_ID, POSTING_SUBJECT, POSTING_BODY):
        "  "
        REQUEST = self.REQUEST


        RESPONSE =    REQUEST.RESPONSE

        POSTING_ID = self.posting_get_posting_id_seq_nextval()[0][0]
        self.posting_insert_sql(POSTING_ID=POSTING_ID, MESSAGE_BOARD_ID=self.MESSAGE_BOARD_ID, PARENT_ID='',
            THREAD_ID='', AUTHOR_IP_ADDRESS=REQUEST['HTTP_X_FORWARDED_FOR'], POSTING_SUBJECT=POSTING_SUBJECT,
            POSTING_BODY=POSTING_BODY)

        def isalnum_or_whitespace(s):
            return s.isalnum() or len(filter(None, ''.join(s.split()))) == 0

        distinct_subject_words = []
        distinct_body_words = []

        posting_subject_filtered = filter(isalnum_or_whitespace, POSTING_SUBJECT)
        posting_subject_list = posting_subject_filtered.split()
        posting_subject_list = map(upper, posting_subject_list)
        for word in posting_subject_list:
            if len(word) > 3:
                if word[-1] == 'S':
                    word = word[:-1]
            if not word in distinct_subject_words:
                distinct_subject_words.append(word)

        posting_body_filtered = filter(isalnum_or_whitespace, POSTING_BODY)
        posting_body_list = posting_body_filtered.split()
        posting_body_list = map(upper, posting_body_list)
        for word in posting_body_list:
            if len(word) > 3:
                if word[-1] == 'S':
                    word = word[:-1]
            if not word in distinct_body_words:
                distinct_body_words.append(word)

        self.posting_keyword_insert_sql(POSTING_ID=POSTING_ID, KEYWORD_LIST=distinct_subject_words,
            KEYWORD_IN_SUBJECT=1)

        self.posting_keyword_insert_sql(POSTING_ID=POSTING_ID, KEYWORD_LIST=distinct_body_words,
            KEYWORD_IN_SUBJECT='')



    def thread_parse_all_messages_into_dict (self, res):
        "  "
        REQUEST = self.REQUEST

        ret = {}
        ret['postings'] = {}
        ret['postings_with_children'] = []

        for rec in res:
            posting_id = rec['posting_id']
            parent_id = rec['parent_id']
            thread_id = rec['thread_id']
            author = rec['author']
            posting_subject = rec['posting_subject']
            posting_body = rec['posting_body']
            date_created = rec['date_created']
            date_last_reply = rec['date_last_reply']
            number_of_replies = rec['number_of_replies']
            posting_priority = rec['posting_priority']
            thread_locked = rec['thread_locked']

            ret['postings'][posting_id] = {}
            ret['postings'][posting_id]['posting_id'] = posting_id
            ret['postings'][posting_id]['parent_id'] = parent_id
            ret['postings'][posting_id]['thread_id'] = thread_id
            ret['postings'][posting_id]['author'] = author
            ret['postings'][posting_id]['posting_subject'] = posting_subject
            ret['postings'][posting_id]['posting_body'] = posting_body
            ret['postings'][posting_id]['date_created'] = date_created
            ret['postings'][posting_id]['date_last_reply'] = date_last_reply
            ret['postings'][posting_id]['number_of_replies'] = number_of_replies
            ret['postings'][posting_id]['thread_locked'] = thread_locked

            if parent_id == None:
                ret['thread_posting_id'] = posting_id
                ret['thread_priority'] = posting_priority
            else:
                if not ret.has_key(str(parent_id) + '_children'):
                    ret[str(parent_id) + '_children'] = []
                    ret['postings_with_children'].append(parent_id)
                ret[str(parent_id) + '_children'].append(posting_id)

        return ret



    def reply_add_action (self, MESSAGE_BOARD_ID, POSTING_SUBJECT, POSTING_BODY, PARENT_POSTING_ID, THREAD_ID):
        "  "
        REQUEST = self.REQUEST
        RESPONSE =    REQUEST.RESPONSE

        POSTING_ID = self.posting_get_posting_id_seq_nextval()[0][0]
        self.posting_insert_sql(POSTING_ID=POSTING_ID, MESSAGE_BOARD_ID=self.MESSAGE_BOARD_ID,
            PARENT_ID=PARENT_POSTING_ID, THREAD_ID=THREAD_ID, AUTHOR_IP_ADDRESS=REQUEST['HTTP_X_FORWARDED_FOR'],
            POSTING_SUBJECT=POSTING_SUBJECT, POSTING_BODY=POSTING_BODY)

        if int(THREAD_ID) == int(PARENT_POSTING_ID):
            self.posting_update_increment_number_of_replies(PARENT_ID=PARENT_POSTING_ID)
        else:
            self.posting_update_increment_number_of_replies(PARENT_ID=PARENT_POSTING_ID)
            self.posting_update_increment_number_of_replies(PARENT_ID=THREAD_ID)

        def isalnum_or_whitespace(s):
            return s.isalnum() or len(filter(None, ''.join(s.split()))) == 0

        distinct_subject_words = []
        distinct_body_words = []

        posting_subject_filtered = filter(isalnum_or_whitespace, POSTING_SUBJECT)
        posting_subject_list = posting_subject_filtered.split()
        posting_subject_list = map(upper, posting_subject_list)
        for word in posting_subject_list:
            if len(word) > 3:
                if word[-1] == 'S':
                    word = word[:-1]
            if not word in distinct_subject_words:
                distinct_subject_words.append(word)

        posting_body_filtered = filter(isalnum_or_whitespace, POSTING_BODY)
        posting_body_list = posting_body_filtered.split()
        posting_body_list = map(upper, posting_body_list)
        for word in posting_body_list:
            if len(word) > 3:
                if word[-1] == 'S':
                    word = word[:-1]
            if not word in distinct_body_words:
                distinct_body_words.append(word)

        self.posting_keyword_insert_sql(POSTING_ID=POSTING_ID, KEYWORD_LIST=distinct_subject_words,
            KEYWORD_IN_SUBJECT=1)

        self.posting_keyword_insert_sql(POSTING_ID=POSTING_ID, KEYWORD_LIST=distinct_body_words,
            KEYWORD_IN_SUBJECT='')



    def posting_edit_action (self, MESSAGE_BOARD_ID, POSTING_ID, POSTING_SUBJECT, POSTING_BODY):
        "  "
        REQUEST = self.REQUEST
        RESPONSE =    REQUEST.RESPONSE

        POSTING_ID=POSTING_ID

        self.posting_update_sql(POSTING_ID=POSTING_ID, POSTING_SUBJECT=POSTING_SUBJECT,
            POSTING_BODY=POSTING_BODY, AUTHOR_IP_ADDRESS=REQUEST['HTTP_X_FORWARDED_FOR'])

        def isalnum_or_whitespace(s):
            return s.isalnum() or len(filter(None, ''.join(s.split()))) == 0

        distinct_subject_words = []
        distinct_body_words = []

        posting_subject_filtered = filter(isalnum_or_whitespace, POSTING_SUBJECT)
        posting_subject_list = posting_subject_filtered.split()
        posting_subject_list = map(upper, posting_subject_list)
        for word in posting_subject_list:
            if len(word) > 3:
                if word[-1] == 'S':
                    word = word[:-1]
            if not word in distinct_subject_words:
                distinct_subject_words.append(word)

        posting_body_filtered = filter(isalnum_or_whitespace, POSTING_BODY)
        posting_body_list = posting_body_filtered.split()
        posting_body_list = map(upper, posting_body_list)
        for word in posting_body_list:
            if len(word) > 3:
                if word[-1] == 'S':
                    word = word[:-1]
            if not word in distinct_body_words:
                distinct_body_words.append(word)

        self.posting_keyword_delete_sql(POSTING_ID=POSTING_ID)

        self.posting_keyword_insert_sql(POSTING_ID=POSTING_ID, KEYWORD_LIST=distinct_subject_words,
            KEYWORD_IN_SUBJECT=1)

        self.posting_keyword_insert_sql(POSTING_ID=POSTING_ID, KEYWORD_LIST=distinct_body_words,
            KEYWORD_IN_SUBJECT='')



    def posting_delete_with_all_children (self, POSTING_ID):
        "  "
        REQUEST = self.REQUEST

        for child in self.posting_get_children(POSTING_ID=POSTING_ID):
            self.posting_delete_with_all_children(POSTING_ID=child['POSTING_ID'])

        self.posting_delete_and_update_parents_sql(POSTING_ID=POSTING_ID)



    def thread_lock_action (self, THREAD_ID):
        "  "
        REQUEST = self.REQUEST
        RESPONSE =    REQUEST.RESPONSE

        if self.user_has_required_role__message_board():
            self.thread_change_locked_status(THREAD_ID=THREAD_ID, NEW_STATUS=1)
            RESPONSE.redirect(REQUEST.get('URL1') + '/thread_view?THREAD_ID=' + str(THREAD_ID))
        else:
            RESPONSE.redirect(REQUEST.get('URL1'))



    def thread_unlock_action (self, THREAD_ID):
        "  "
        REQUEST = self.REQUEST
        RESPONSE =    REQUEST.RESPONSE

        if self.user_has_required_role__message_board():
            self.thread_change_locked_status(THREAD_ID=THREAD_ID, NEW_STATUS=0)
            RESPONSE.redirect(REQUEST.get('URL1') + '/thread_view?THREAD_ID=' + str(THREAD_ID))
        else:
            RESPONSE.redirect(REQUEST.get('URL1'))



    def thread_set_priority_to_normal_action (self, THREAD_ID):
        "  "
        REQUEST = self.REQUEST
        RESPONSE =    REQUEST.RESPONSE

        if self.user_has_required_role__message_board():
            self.thread_change_priority_sql(THREAD_ID=THREAD_ID, NEW_PRIORITY=10)
            RESPONSE.redirect(REQUEST.get('URL1') + '/thread_view?THREAD_ID=' + str(THREAD_ID))
        else:
            RESPONSE.redirect(REQUEST.get('URL1'))



    def thread_set_priority_to_high_action (self, THREAD_ID):
        "  "
        REQUEST = self.REQUEST
        RESPONSE =    REQUEST.RESPONSE

        if self.user_has_required_role__message_board():
            self.thread_change_priority_sql(THREAD_ID=THREAD_ID, NEW_PRIORITY=5)
            RESPONSE.redirect(REQUEST.get('URL1') + '/thread_view?THREAD_ID=' + str(THREAD_ID))
        else:
            RESPONSE.redirect(REQUEST.get('URL1'))



    def remove_tags_from_string (self, a=''):
        "  "
        REQUEST = self.REQUEST

        taglessString = ''
        inTag = 0

        if str(a).find('<') == -1:
            return a

        if str(a).find('>') == -1:
            return a

        string_len = len(a)
        for index in range(0,string_len):
            if a[index] != '<' and inTag == 0:
                taglessString = taglessString + str(a[index])
            else:
                if a[index] == '<':
                    inTag = 1
                elif inTag == 1:
                    if a[index] == '>':
                        inTag = 0

        return taglessString



    def message_board_search_results_process_search_term (self, search_term):
        "  "
        REQUEST = self.REQUEST

        ret = []

        def isalnum_or_whitespace(s):
            return s.isalnum() or len(filter(None, ''.join(s.split()))) == 0

        distinct_search_term_words = []

        search_terms_filtered = filter(isalnum_or_whitespace, search_term)
        search_term_list = search_terms_filtered.split()
        search_term_list = map(upper, search_term_list)
        for word in search_term_list:
            if len(word) > 3:
                if word[-1] == 'S':
                    word = word[:-1]
            if not word in distinct_search_term_words:
                distinct_search_term_words.append(word)

        return distinct_search_term_words



    def user_has_required_role__message_board (self):
        "  "
        user = SecurityManagement.getSecurityManager().getUser()
        return  user.has_role(['Moderator', 'Admin', 'Manager'], self)

    accent_color_primary = '#DFDFFF'
    accent_color_secondary = '#F9F9FF'

00514     def SQLConnectionIDs(self):
        """Find SQL database connections in the current folder and above

        This function return a list of ids.
        """
        ids={}
        have_id=ids.has_key
        StringType=type('')

        while self is not None:
            if hasattr(self, 'objectValues'):
                for o in self.objectValues():
                    if (hasattr(o,'_isAnSQLConnection') and o._isAnSQLConnection
                        and hasattr(o,'id')):
                        id=o.id
                        if type(id) is not StringType: id=id()
                        if not have_id(id):
                            if hasattr(o,'title_and_id'): o=o.title_and_id()
                            else: o=id
                            ids[id]=id
            if hasattr(self, 'aq_parent'): self=self.aq_parent
            else: self=None

        ids=map(lambda item: (item[1], item[0]), ids.items())
        ids.sort()
        return ids

# attach dtml files to the class
for fn in os.listdir(package_home(globals()) + '/dtml'):
    id = fn[:-5] # strip the ext
    setattr(CMFpgForum, id, HTMLFile('dtml/' + id, globals() ) )

# attach img files to the class
for fn in os.listdir(package_home(globals()) + '/img'):
    setattr(CMFpgForum, fn, ImageFile('img/' + fn, globals() ) )

InitializeClass(CMFpgForum)




Generated by  Doxygen 1.6.0   Back to index