# -*- coding: utf-8 -*- # # File: exportimport.py # # Copyright (c) 2006 by CommunesPlone # # GNU General Public License (GPL) # # 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., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # __author__ = """Gauthier BASTIEN Stéphan GEULETTE """ __docformat__ = 'plaintext' """ teleservices exportimport setup This is the exportimport file for GenericSetup, see configure.zcml and profiles/default for more informations """ from zLOG import INFO, ERROR from Products.TeleServices.config import * from Products.CMFCore.utils import getToolByName from Products.PlacelessTranslationService import utranslate from Products.Archetypes import listTypes, transaction from Products.CMFCore.permissions import ListUndoableChanges import os.path from zExceptions import BadRequest import logging logger = logging.getLogger('TeleServices') def installProducts(context): """ Install necessary products """ portal = context.getSite() qi = getToolByName(portal, 'portal_quickinstaller') if not qi.isProductInstalled('Archetypes'): qi.installProduct('Archetypes') if not qi.isProductInstalled('TeleServices'): qi.installProduct('TeleServices') # get_transaction().commit(1) transaction.commit() return "Necessary products for TeleServices installed." def createFolderHierarchy(context): """ We add the folder hierarchy if we want """ #--> create a default folder hierarchy #--> one root_folder containing # --> one folder by content_type # --> one smart folder by workflow state portal = context.getSite() def publishFolderContent(containr): #we publish every folder and sub folder contained in the root_folder from Products.PlacelessTranslationService import utranslate publish_comment = "published_at_install_time" #publish_comment = utranslate(domain="teleservices", msgid="published_at_install_time", default="Published at install time", context=portal) for folder in containr.objectValues(): for transition in wft.getTransitionsFor(folder): if "publish" == transition['id']: wft.doActionFor(folder, "publish", comment=publish_comment) break try: wft = getToolByName(portal, 'portal_workflow') list_klasses = listTypes(PROJECTNAME) #we do not want the content_types GenericTeleService and TeleServicesTool to be used, so, we remove it from klasses ind_dict = 0 klasses = [] for klasse in list_klasses: if klasse['name'] not in EXCLUDED_TYPES: klasses.append(klasse) #create the smart folders by content_type and by workflow states tool = getToolByName(portal, 'portal_teleservices') #we create ATTopics to lookup every content_types and the searchformylast #searchforallmyteleservices tool.invokeFactory(type_name='Topic', id=ATTOPIC_ALL_NAME) attopic = getattr(tool, ATTOPIC_ALL_NAME) attopic.setExcludeFromNav(True) attopic.setTitle(ATTOPIC_ALL_NAME) criterion = attopic.addCriterion(field='Type', criterion_type='ATPortalTypeCriterion') criterion.setValue([klass['portal_type'] for klass in klasses]) #on limite a 25 resultats par page attopic.setLimitNumber(True) attopic.setItemCount(20) attopic.setSortCriterion('created', True) #on fabrique une vue personnalisee attopic.setCustomView(True) attopic.setCustomViewFields(['Title', 'review_state', 'Creator', 'getNationalRegister', 'getTransmissionDate', 'Type']) #default search for citizen tool.invokeFactory(type_name='Topic', id=ATTOPIC_CITIZEN_DEFAULT) attopic = getattr(tool, ATTOPIC_CITIZEN_DEFAULT) attopic.setExcludeFromNav(True) attopic.setTitle(ATTOPIC_CITIZEN_DEFAULT) criterion = attopic.addCriterion(field='Type', criterion_type='ATPortalTypeCriterion') criterion.setValue([klass['portal_type'] for klass in klasses]) attopic.setLimitNumber(True) attopic.setItemCount(5) attopic.setSortCriterion('created', True) #on fabrique une vue personnalisee attopic.setCustomView(True) attopic.setCustomViewFields(['Title', 'review_state', 'Type', 'getTransmissionDate']) #default search for manager tool.invokeFactory(type_name='Topic', id=ATTOPIC_MANAGER_DEFAULT) attopic = getattr(tool, ATTOPIC_MANAGER_DEFAULT) attopic.setExcludeFromNav(True) attopic.setTitle(ATTOPIC_MANAGER_DEFAULT) criterion = attopic.addCriterion(field='Type', criterion_type='ATPortalTypeCriterion') criterion.setValue([klass['portal_type'] for klass in klasses]) # criterion = attopic.addCriterion(field='expirationDate', criterion_type='ATDateCriteria') # criterion.setOperation('less') # criterion.setDateRange('-') # criterion.setValue(0) toTreatStates = [] for klass in klasses: for workflow in wft.getWorkflowsFor(klass['name']): for value in workflow.states.values(): if value.getId() in ('transmitted', 'in_treatment') and value.getId() not in toTreatStates: toTreatStates.append(value.getId()) criterion = attopic.addCriterion(field='review_state', criterion_type='ATListCriterion') criterion.setValue(toTreatStates) attopic.setLimitNumber(True) attopic.setItemCount(20) attopic.setSortCriterion('created', True) #on fabrique une vue personnalisee attopic.setCustomView(True) attopic.setCustomViewFields(['Title', 'review_state', 'Creator', 'getNationalRegister', 'getTransmissionDate', 'Type']) #searchforlast tool.invokeFactory(type_name='Topic', id=ATTOPIC_LAST_NAME) attopic = getattr(tool, ATTOPIC_LAST_NAME) attopic.setExcludeFromNav(True) attopic.setTitle(ATTOPIC_LAST_NAME) criterion = attopic.addCriterion(field='Type', criterion_type='ATPortalTypeCriterion') criterion.setValue([klass['portal_type'] for klass in klasses]) #on limite a ATTOPIC_LAST_ITEM_COUNT resultats par page attopic.setLimitNumber(True) attopic.setItemCount(ATTOPIC_LAST_ITEM_COUNT) attopic.setSortCriterion('created', True) #on fabrique une vue personnalisee attopic.setCustomView(True) attopic.setCustomViewFields(['Title', 'review_state', 'Creator', 'getNationalRegister', 'getTransmissionDate', 'Type']) for klass in klasses: klass_portal_type = klass['name'] if not hasattr(tool, klass_portal_type.lower() + '_config'): #we create the config folder for a type tool.invokeFactory(type_name='Folder', id= klass_portal_type.lower() + '_config') folder = getattr(tool, klass_portal_type.lower() + '_config') folder.setTitle(klass_portal_type) #we create an ATTopic by workflow state, here we manage the workflow of the content_type for workflow in wft.getWorkflowsFor(klass_portal_type): for value in workflow.states.values(): try: generated_id = "searchfor" + value.getId() folder.invokeFactory(type_name="Topic", id=generated_id) attopic = getattr(folder, generated_id) attopic.setExcludeFromNav(True) #we set the title from the msgid we have generated with the id of the attopic attopic.setTitle(generated_id) #criterion of type --> the content_type = klass_portal_type criterion = attopic.addCriterion(field='Type', criterion_type='ATPortalTypeCriterion') criterion.setValue([klass['portal_type']]) #criterion of state criterion = attopic.addCriterion(field='review_state', criterion_type='ATListCriterion') criterion.value = (value.getId(), ) #we sort on creation date, the older first #criterion = attopic.addCriterion(field='created', criterion_type='ATSortCriterion') attopic.setSortCriterion('created', True) #we limit to 25 results by page attopic.setLimitNumber(True) attopic.setItemCount(20) #we make our personnal view attopic.setCustomView(True) attopic.setCustomViewFields(['Title', 'review_state', 'Creator', 'getNationalRegister', 'getTransmissionDate', 'Type']) except: # import traceback # traceback.print_exc() print "Generated id : %s raises error. Already created in previous class workflow state" % generated_id publishFolderContent(folder) publishFolderContent(tool) except BadRequest: logger.warn("The createFolderHierarchy method has already been executed !") def permissionsForMembersPersonnalFolder(context): """ We set the permissions on "my folder" We accept the add of a content_type or not """ portal = context.getSite() ind_dict = 0 klasses = listTypes(PROJECTNAME) for klasse in klasses: if klasse['name'] == 'GenericTeleService' or klasse['name'] == 'TeleServicesTool': klasses.pop(ind_dict) ind_dict += 1 for klass in klasses: if ALLOW_ADD_IN_MEMBERS: portal.Members.manage_permission(ADD_CONTENT_PERMISSIONS[klass['name']],("Manager", "Owner", ),acquire=1) else: portal.Members.manage_permission(ADD_CONTENT_PERMISSIONS[klass['name']],("Manager", ),acquire=1) def hideUselessActions(context): """ We remove here every actions that could disturb the user --> 'cancel' """ #we do not remove the action, we 'play' with Permissions #we remove the 'List undoable changes' to the role Member to remove the "cancel" action portal = context.getSite() portal.manage_permission(ListUndoableChanges,("Manager", "TeleServicesManager", ),acquire=0) #we exclude Members from the navigation portal.Members.setExcludeFromNav(True) def removeUselessObjects(context): """ We remove here objects that could disturb the user --> ATTopic events --> ATTopic news """ portal = context.getSite() try: portal.manage_delObjects('events') except AttributeError: print "No ATTopic named 'events' was found!" try: portal.manage_delObjects('news') except AttributeError: print "No ATTopic named 'news' was found!" def updateSlots(context): """ We remove everything from right_slot We set left_slot with only the navigation portlet """ portal = context.getSite() portal.manage_changeProperties(right_slots = ('', )) portal.manage_changeProperties(left_slots = ('here/portlet_navigation/macros/portlet', )) def runEverySteps(context): installProducts(context) createFolderHierarchy(context) permissionsForMembersPersonnalFolder(context) hideUselessActions(context) removeUselessObjects(context) updateSlots(context) def addDefaultExampleConfig(context): """ Adding the default english example configuration """ portal = context.getSite() from Products.TeleServices.profiles.default.default_config import MOTIVTERMS, DESTTERMS, DEMANDTERMS addExampleConfig(context, portal, MOTIVTERMS, DESTTERMS, DEMANDTERMS, False) def addFrenchExampleConfig(context): """ Adding the french example configuration """ portal = context.getSite() from Products.TeleServices.profiles.example_fr_config.default_config import MOTIVTERMS, DESTTERMS, DEMANDTERMS addExampleConfig(context, portal, MOTIVTERMS, DESTTERMS, DEMANDTERMS, True) def addItalianExampleConfig(context): """ Adding the it example configuration """ portal = context.getSite() from Products.TeleServices.profiles.example_it_config.default_config import MOTIVTERMS, DESTTERMS, DEMANDTERMS addExampleConfig(context, portal, MOTIVTERMS, DESTTERMS, DEMANDTERMS, True) def addExampleConfig(context, portal, motivterms, destterms, demandterms, delete_existing): """ Add examples terms in the teleservices configuration """ tst = getToolByName(portal, 'portal_teleservices') wft = portal.portal_workflow toCreateFlags = {} def getBaseFolder(classname): #get the tool config folder corresponding to the ts class #create if non-existent folder_id = classname.lower() + '_config' if not hasattr(tst, folder_id): tst.invokeFactory('Folder', folder_id) obj = getattr(tst, folder_id) obj.setTitle(classname) return getattr(tst, folder_id) def getTermsObjects(classname, termname, *ids): #return the terms objects list corresponding to given ids objs = [] for termid in ids: obj = tst.getTermObject(classname, termname, termid) if obj is not None: objs.append(obj) else: logger.warn("TeleServices: termid '%s' of type '%s' not found" % (termid, termname)) return objs def createFolderAndTerms(baseFolder, className, termName, **dic ): #we do nothing if the folder exists to avoid overwrite of manually created data folderName = termName + 's' # if delete_existing: # baseFolder.manage_delObjects(folderName.lower()) if not hasattr(baseFolder, folderName.lower()): baseFolder.invokeFactory('Folder', folderName.lower()) folder = getattr(baseFolder, folderName.lower()) folder.setTitle(folderName) folder.setConstrainTypesMode(1) folder.setLocallyAllowedTypes([termName]) #we HAVE TO setImmediatelyAddableTypes here because of a bug #--> if immediatelyAddableTypes is not set, we have a validation problem if we try to add a folder here #--> we do not add Folder here but well... ;-) folder.setImmediatelyAddableTypes([termName]) folder.reindexObject() #logger.info('creating folder:'+folderName) toCreateFlags[classname][folderName] = True if not toCreateFlags[classname].has_key(folderName): #logger.info('return') return folder = getattr(baseFolder, folderName.lower()) ikey = dic['id'] # logger.info('ikey:'+ikey) if dic.has_key('motivationTerms'): dic['motivationTerms'] = getTermsObjects(classname, 'MotivationTerm', *dic['motivationTerms']) #logger.info(dic['motivationTerms']) if dic.has_key('destinationTerms'): dic['destinationTerms'] = getTermsObjects(classname, 'DestinationTerm', *dic['destinationTerms']) #logger.info(dic['destinationTerms']) if not hasattr(folder, ikey): # logger.info('before invoke') id = folder.invokeFactory(termName, **dic) logger.info("TeleServices: creating in class %s, term %s, object value %s"%(className,termName,ikey)) if dic.has_key('info_only') and dic['info_only']: term = getattr(folder, id) wft.doActionFor(term, 'for_info_only') logger.info('TeleServices: demandtypeterm set to info_only state') if dic.has_key('disabled') and dic['disabled']: term = getattr(folder, id) wft.doActionFor(term, 'disable') logger.info('TeleServices: term set to disabled') def delete_configfolder(baseFolder, termName): folderName = termName + 's' baseFolder.manage_delObjects(folderName.lower()) logger.info('TeleServices: installing example terms') for classname in motivterms: bf = getBaseFolder(classname) toCreateFlags[classname] = {} if delete_existing: delete_configfolder(bf, 'MotivationTerm') for dic in motivterms[classname]: createFolderAndTerms(bf, classname, 'MotivationTerm', **dic) for classname in destterms: bf = getBaseFolder(classname) toCreateFlags[classname] = {} if delete_existing: delete_configfolder(bf, 'DestinationTerm') for dic in destterms[classname]: createFolderAndTerms(bf, classname, 'DestinationTerm', **dic) for classname in demandterms: bf = getBaseFolder(classname) toCreateFlags[classname] = {} if delete_existing: delete_configfolder(bf, 'DemandTypeTerm') for dic in demandterms[classname]: createFolderAndTerms(bf, classname, 'DemandTypeTerm', **dic) #Creating index_html file logger.info('TeleServices:Creating index_html file') # if not hasattr(portal, 'index_html'): This doesn't work because hasattr() uses acquisition !!!! from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate profilepath = context._profile_path if 'index_html' not in portal.objectIds(): path = os.path.join(profilepath, 'index_html_root.pt') if os.path.exists(path): fd = open(path, 'r') zpt = ZopePageTemplate('index_html', fd) portal._setObject('index_html', zpt) fd.close() #Adapting front-page logger.info('TeleServices:Adapting front-page') cfp = None if hasattr(portal, 'front-page'): cfp = getattr(portal, 'front-page') if cfp.Title() == 'Welcome to Plone' and cfp.getText().find('Tell us how you use Plone') >= 0: path = os.path.join(profilepath, 'front-page.txt') if os.path.exists(path): fd = open(path, 'r') title = fd.readline() cfp.edit(text_format='html', text = fd.read()) fd.close() cfp.setTitle(title) cfp.setDescription('') cfp.setExcludeFromNav(True) cfp.reindexObject() path = os.path.join(profilepath, 'eid.txt') if os.path.exists(path) and not hasattr(portal, 'eid'): portal.invokeFactory('Document', 'eid') fd = open(path, 'r') title = fd.readline() eid = getattr(portal, 'eid') eid.edit(text_format='html', text = fd.read()) fd.close() eid.setTitle(title) eid.setDescription('') eid.setExcludeFromNav(True) eid.reindexObject() def testProfile(context): """ test profile for PloneTestCase """ portal = context.getSite() from Products.TeleServices.profiles.test.default_config import MOTIVTERMS, DESTTERMS, DEMANDTERMS addExampleConfig(context, portal, MOTIVTERMS, DESTTERMS, DEMANDTERMS, True)