Back to index

plone3  3.1.7
setuphandlers.py
Go to the documentation of this file.
00001 """
00002 CMFPlone setup handlers.
00003 """
00004 
00005 from five.localsitemanager import make_objectmanager_site
00006 from zope.app.component.interfaces import ISite
00007 from zope.app.component.hooks import setSite
00008 from zope.component import getUtility
00009 from zope.component import getMultiAdapter
00010 from zope.component import queryUtility
00011 
00012 from zope.event import notify
00013 from zope.i18n.interfaces import ITranslationDomain
00014 from zope.i18n.interfaces import IUserPreferredLanguages
00015 from zope.i18n.locales import locales, LoadLocaleError
00016 from zope.interface import implements
00017 
00018 from Acquisition import aq_base, aq_get
00019 from Products.StandardCacheManagers.AcceleratedHTTPCacheManager import \
00020      AcceleratedHTTPCacheManager
00021 from Products.StandardCacheManagers.RAMCacheManager import \
00022      RAMCacheManager
00023 
00024 from Products.CMFCore.utils import getToolByName
00025 from Products.CMFPlone.utils import _createObjectByType
00026 from Products.CMFPlone import migrations as migs
00027 from Products.CMFPlone.events import SiteManagerCreatedEvent
00028 from Products.CMFPlone.Portal import member_indexhtml
00029 from Products.ATContentTypes.lib import constraintypes
00030 from Products.CMFQuickInstallerTool.interfaces import INonInstallable
00031 
00032 from plone.i18n.normalizer.interfaces import IURLNormalizer
00033 from plone.portlets.interfaces import IPortletAssignmentMapping
00034 from plone.portlets.interfaces import IPortletManager
00035 from plone.portlets.interfaces import ILocalPortletAssignmentManager
00036 from plone.portlets.constants import CONTEXT_CATEGORY as CONTEXT_PORTLETS
00037 from plone.app.portlets import portlets
00038 
00039 from Products.CMFPlone.interfaces import IMigrationTool
00040 
00041 from Products.PlonePAS.plugins.local_role import LocalRolesManager
00042 from borg.localrole.utils import setup_localrole_plugin
00043 
00044 
00045 class HiddenProducts(object):
00046     implements(INonInstallable)
00047 
00048     def getNonInstallableProducts(self):
00049         return [
00050             'Archetypes', 'Products.Archetypes',
00051             'ATContentTypes', 'Products.ATContentTypes',
00052             'ATReferenceBrowserWidget', 'Products.ATReferenceBrowserWidget',
00053             'CMFActionIcons', 'Products.CMFActionIcons',
00054             'CMFCalendar', 'Products.CMFCalendar',
00055             'CMFDefault', 'Products.CMFDefault',
00056             'CMFPlone', 'Products.CMFPlone', 'Products.CMFPlone.migrations',
00057             'CMFTopic', 'Products.CMFTopic',
00058             'CMFUid', 'Products.CMFUid',
00059             'DCWorkflow', 'Products.DCWorkflow',
00060             'GroupUserFolder', 'Products.GroupUserFolder',
00061             'PasswordResetTool', 'Products.PasswordResetTool',
00062             'PlonePAS', 'Products.PlonePAS',
00063             'wicked.at',
00064             'kupu', 'Products.kupu',
00065             'PloneLanguageTool', 'Products.PloneLanguageTool',
00066             'Kupu', 'Products.Kupu',
00067             'CMFFormController', 'Products.CMFFormController',
00068             'MimetypesRegistry', 'Products.MimetypesRegistry',
00069             'PortalTransforms', 'Products.PortalTransforms',
00070             'CMFDiffTool', 'Products.CMFDiffTool',
00071             'CMFEditions', 'Products.CMFEditions',
00072             'Products.NuPlone',
00073             'plone.portlet.static',
00074             'plone.portlet.collection',
00075             'borg.localrole',
00076             'plone.keyring',
00077             'plone.protect',
00078             ]
00079 
00080 
00081 class PloneGenerator:
00082 
00083     def installArchetypes(self, p):
00084         """QuickInstaller install of Archetypes and required dependencies."""
00085         qi = getToolByName(p, "portal_quickinstaller")
00086         qi.installProduct('CMFFormController', locked=1, hidden=1, forceProfile=True)
00087         qi.installProduct('MimetypesRegistry', locked=1, hidden=1, forceProfile=True)
00088         qi.installProduct('PortalTransforms', locked=1, hidden=1, forceProfile=True)
00089         qi.installProduct('Archetypes', locked=1, hidden=1,
00090             profile=u'Products.Archetypes:Archetypes')
00091 
00092     def installProducts(self, p):
00093         """QuickInstaller install of required Products"""
00094         qi = getToolByName(p, 'portal_quickinstaller')
00095         qi.installProduct('PlonePAS', locked=1, hidden=1, forceProfile=True)
00096         qi.installProduct('kupu', locked=0, forceProfile=True)
00097         qi.installProduct('CMFDiffTool', locked=0, forceProfile=True)
00098         qi.installProduct('CMFEditions', locked=0, forceProfile=True)
00099         qi.installProduct('PloneLanguageTool', locked=1, hidden=1, forceProfile=True)
00100 
00101     def installDependencies(self, p):
00102         st=getToolByName(p, "portal_setup")
00103         st.runAllImportStepsFromProfile("profile-Products.CMFPlone:dependencies")
00104 
00105 
00106     def addCacheHandlers(self, p):
00107         """ Add RAM and AcceleratedHTTP cache handlers """
00108         mgrs = [(AcceleratedHTTPCacheManager, 'HTTPCache'),
00109                 (RAMCacheManager, 'RAMCache'),
00110                 (RAMCacheManager, 'ResourceRegistryCache'),
00111                 ]
00112         for mgr_class, mgr_id in mgrs:
00113             existing = p._getOb(mgr_id, None)
00114             if existing is None:
00115                 p._setObject(mgr_id, mgr_class(mgr_id))
00116             else:
00117                 unwrapped = aq_base(existing)
00118                 if not isinstance(unwrapped, mgr_class):
00119                     p._delObject(mgr_id)
00120                     p._setObject(mgr_id, mgr_class(mgr_id))
00121 
00122     def addCacheForResourceRegistry(self, portal):
00123         ram_cache_id = 'ResourceRegistryCache'
00124         if ram_cache_id in portal.objectIds():
00125             cache = getattr(portal, ram_cache_id)
00126             settings = cache.getSettings()
00127             settings['max_age'] = 24*3600 # keep for up to 24 hours
00128             settings['request_vars'] = ('URL',)
00129             cache.manage_editProps('Cache for saved ResourceRegistry files', settings)
00130         reg = getToolByName(portal, 'portal_css', None)
00131         if reg is not None and getattr(aq_base(reg), 'ZCacheable_setManagerId', None) is not None:
00132             reg.ZCacheable_setManagerId(ram_cache_id)
00133             reg.ZCacheable_setEnabled(1)
00134 
00135         reg = getToolByName(portal, 'portal_kss', None)
00136         if reg is not None and getattr(aq_base(reg), 'ZCacheable_setManagerId', None) is not None:
00137             reg.ZCacheable_setManagerId(ram_cache_id)
00138             reg.ZCacheable_setEnabled(1)
00139 
00140         reg = getToolByName(portal, 'portal_javascripts', None)
00141         if reg is not None and getattr(aq_base(reg), 'ZCacheable_setManagerId', None) is not None:
00142             reg.ZCacheable_setManagerId(ram_cache_id)
00143             reg.ZCacheable_setEnabled(1)
00144 
00145     # XXX: This should all be done by custom setuphandlers
00146     def setupPortalContent(self, p):
00147         """
00148         Import default plone content
00149         """
00150         existing = p.objectIds()
00151 
00152         wftool = getToolByName(p, "portal_workflow")
00153 
00154         # Figure out the current user preferred language
00155         language = None
00156         locale = None
00157         target_language = None
00158         request = getattr(p, 'REQUEST', None)
00159         if request is not None:
00160             pl = IUserPreferredLanguages(request)
00161             if pl is not None:
00162                 languages = pl.getPreferredLanguages()
00163                 for httplang in languages:
00164                     parts = (httplang.split('-') + [None, None])[:3]
00165                     try:
00166                         locale = locales.getLocale(*parts)
00167                         break
00168                     except LoadLocaleError:
00169                         # Just try the next combination
00170                         pass
00171                 if len(languages) > 0:
00172                     language = languages[0]
00173 
00174         # Language to be used to translate the content
00175         target_language = language
00176 
00177         # Set the default language of the portal
00178         if language is not None and locale is not None:
00179             localeid = locale.getLocaleID()
00180             base_language = locale.id.language
00181             target_language = localeid
00182 
00183             # If we get a territory, we enable the combined language codes
00184             use_combined = False
00185             if locale.id.territory:
00186                 use_combined = True
00187 
00188             # As we have a sensible language code set now, we disable the
00189             # start neutral functionality
00190             tool = getToolByName(p, "portal_languages")
00191             pprop = getToolByName(p, "portal_properties")
00192             sheet = pprop.site_properties
00193 
00194             tool.manage_setLanguageSettings(language,
00195                 [language],
00196                 setUseCombinedLanguageCodes=use_combined,
00197                 startNeutral=False)
00198 
00199             # Enable visible_ids for non-latin scripts
00200 
00201             # See if we have an url normalizer
00202             normalizer = queryUtility(IURLNormalizer, name=localeid)
00203             if normalizer is None:
00204                 normalizer = queryUtility(IURLNormalizer, name=base_language)
00205 
00206             # If we get a script other than Latn we enable visible_ids
00207             if locale.id.script is not None:
00208                 if locale.id.script.lower() != 'latn':
00209                     sheet.visible_ids = True
00210 
00211             # If we have a normalizer it is safe to disable the visible ids
00212             if normalizer is not None:
00213                 sheet.visible_ids = False
00214 
00215         # Special handling of the front-page, as we want to translate it
00216         if 'front-page' in existing:
00217             fp = p['front-page']
00218             if wftool.getInfoFor(fp, 'review_state') != 'published':
00219                 wftool.doActionFor(fp, 'publish')
00220 
00221             # Show off presentation mode
00222             fp.setPresentation(True)
00223 
00224             # Mark as fully created
00225             fp.unmarkCreationFlag()
00226 
00227             if target_language is not None:
00228                 util = queryUtility(ITranslationDomain, 'plonefrontpage')
00229                 if util is not None:
00230                     front_title = util.translate(u'front-title',
00231                                        target_language=target_language,
00232                                        default="Welcome to Plone")
00233                     front_desc = util.translate(u'front-description',
00234                                        target_language=target_language,
00235                                        default="Congratulations! You have successfully installed Plone.")
00236                     front_text = util.translate(u'front-text',
00237                                        target_language=target_language)
00238                     fp.setLanguage(language)
00239                     fp.setTitle(front_title)
00240                     fp.setDescription(front_desc)
00241                     if front_text != u'front-text':
00242                         fp.setText(front_text)
00243 
00244         # News topic
00245         if 'news' not in existing:
00246             news_title = 'News'
00247             news_desc = 'Site News'
00248             if target_language is not None:
00249                 util = queryUtility(ITranslationDomain, 'plonefrontpage')
00250                 if util is not None:
00251                     news_title = util.translate(u'news-title',
00252                                            target_language=target_language,
00253                                            default='News')
00254                     news_desc = util.translate(u'news-description',
00255                                           target_language=target_language,
00256                                           default='Site News')
00257 
00258             _createObjectByType('Large Plone Folder', p, id='news',
00259                                 title=news_title, description=news_desc)
00260             _createObjectByType('Topic', p.news, id='aggregator',
00261                                 title=news_title, description=news_desc)
00262 
00263             folder = p.news
00264             folder.setConstrainTypesMode(constraintypes.ENABLED)
00265             folder.setLocallyAllowedTypes(['News Item'])
00266             folder.setImmediatelyAddableTypes(['News Item'])
00267             folder.setDefaultPage('aggregator')
00268             folder.unmarkCreationFlag()
00269             if language is not None:
00270                 folder.setLanguage(language)
00271 
00272             if wftool.getInfoFor(folder, 'review_state') != 'published':
00273                 wftool.doActionFor(folder, 'publish')
00274 
00275             topic = p.news.aggregator
00276             if language is not None:
00277                 topic.setLanguage(language)
00278             type_crit = topic.addCriterion('Type','ATPortalTypeCriterion')
00279             type_crit.setValue('News Item')
00280             sort_crit = topic.addCriterion('created','ATSortCriterion')
00281             state_crit = topic.addCriterion('review_state', 'ATSimpleStringCriterion')
00282             state_crit.setValue('published')
00283             topic.setSortCriterion('effective', True)
00284             topic.setLayout('folder_summary_view')
00285             topic.unmarkCreationFlag()
00286 
00287             if wftool.getInfoFor(topic, 'review_state') != 'published':
00288                 wftool.doActionFor(topic, 'publish')
00289 
00290         # Events topic
00291         if 'events' not in existing:
00292             events_title = 'Events'
00293             events_desc = 'Site Events'
00294             if target_language is not None:
00295                 util = queryUtility(ITranslationDomain, 'plonefrontpage')
00296                 if util is not None:
00297                     events_title = util.translate(u'events-title',
00298                                            target_language=target_language,
00299                                            default='Events')
00300                     events_desc = util.translate(u'events-description',
00301                                           target_language=target_language,
00302                                           default='Site Events')
00303 
00304             _createObjectByType('Large Plone Folder', p, id='events',
00305                                 title=events_title, description=events_desc)
00306             _createObjectByType('Topic', p.events, id='aggregator',
00307                                 title=events_title, description=events_desc)
00308             folder = p.events
00309             folder.setConstrainTypesMode(constraintypes.ENABLED)
00310             folder.setLocallyAllowedTypes(['Event'])
00311             folder.setImmediatelyAddableTypes(['Event'])
00312             folder.setDefaultPage('aggregator')
00313             folder.unmarkCreationFlag()
00314             if language is not None:
00315                 folder.setLanguage(language)
00316 
00317             if wftool.getInfoFor(folder, 'review_state') != 'published':
00318                 wftool.doActionFor(folder, 'publish')
00319 
00320             topic = folder.aggregator
00321             topic.unmarkCreationFlag()
00322             if language is not None:
00323                 topic.setLanguage(language)
00324             type_crit = topic.addCriterion('Type','ATPortalTypeCriterion')
00325             type_crit.setValue('Event')
00326             sort_crit = topic.addCriterion('start','ATSortCriterion')
00327             state_crit = topic.addCriterion('review_state', 'ATSimpleStringCriterion')
00328             state_crit.setValue('published')
00329             date_crit = topic.addCriterion('start', 'ATFriendlyDateCriteria')
00330             # Set date reference to now
00331             date_crit.setValue(0)
00332             # Only take events in the future
00333             date_crit.setDateRange('+') # This is irrelevant when the date is now
00334             date_crit.setOperation('more')
00335         else:
00336             topic = p.events
00337 
00338         if wftool.getInfoFor(topic, 'review_state') != 'published':
00339             wftool.doActionFor(topic, 'publish')
00340 
00341         # Previous events subtopic
00342         if 'previous' not in topic.objectIds():
00343             prev_events_title = 'Past Events'
00344             prev_events_desc = 'Events which have already happened.'
00345             if target_language is not None:
00346                 util = queryUtility(ITranslationDomain, 'plonefrontpage')
00347                 if util is not None:
00348                     prev_events_title = util.translate(u'prev-events-title',
00349                                            target_language=target_language,
00350                                            default='Past Events')
00351                     prev_events_desc = util.translate(u'prev-events-description',
00352                                           target_language=target_language,
00353                                           default='Events which have already happened.')
00354 
00355             _createObjectByType('Topic', topic, id='previous',
00356                                 title=prev_events_title,
00357                                 description=prev_events_desc)
00358             topic = topic.previous
00359             if language is not None:
00360                 topic.setLanguage(language)
00361             topic.setAcquireCriteria(True)
00362             topic.unmarkCreationFlag()
00363             sort_crit = topic.addCriterion('end','ATSortCriterion')
00364             sort_crit.setReversed(True)
00365             date_crit = topic.addCriterion('end','ATFriendlyDateCriteria')
00366             # Set date reference to now
00367             date_crit.setValue(0)
00368             # Only take events in the past
00369             date_crit.setDateRange('-') # This is irrelevant when the date is now
00370             date_crit.setOperation('less')
00371 
00372             if wftool.getInfoFor(topic, 'review_state') != 'published':
00373                 wftool.doActionFor(topic, 'publish')
00374 
00375         if 'Members' in existing:
00376             # configure Members folder (already added by the content import)
00377             members_title = 'Users'
00378             members_desc = "Container for users' home directories"
00379             if target_language is not None:
00380                 util = queryUtility(ITranslationDomain, 'plonefrontpage')
00381                 if util is not None:
00382                     members_title = util.translate(u'members-title',
00383                                            target_language=target_language,
00384                                            default='Users')
00385                     members_desc = util.translate(u'members-description',
00386                                           target_language=target_language,
00387                                           default="Container for users' home directories")
00388 
00389             members = getattr(p , 'Members')
00390             members.setTitle(members_title)
00391             members.setDescription(members_desc)
00392             members.unmarkCreationFlag()
00393             if language is not None:
00394                 members.setLanguage(language)
00395             members.reindexObject()
00396 
00397             if wftool.getInfoFor(members, 'review_state') != 'published':
00398                 wftool.doActionFor(members, 'publish')
00399 
00400             # add index_html to Members area
00401             if 'index_html' not in members.objectIds():
00402                 addPy = members.manage_addProduct['PythonScripts'].manage_addPythonScript
00403                 addPy('index_html')
00404                 index_html = getattr(members, 'index_html')
00405                 index_html.write(member_indexhtml)
00406                 index_html.ZPythonScript_setTitle('User Search')
00407 
00408     def performMigrationActions(self, p):
00409         """
00410         Perform any necessary migration steps.
00411         """
00412         mt = queryUtility(IMigrationTool)
00413         mt.setInstanceVersion(mt.getFileSystemVersion())
00414 
00415     def enableSyndication(self, portal, out):
00416         syn = getToolByName(portal, 'portal_syndication', None)
00417         if syn is not None:
00418             syn.editProperties(isAllowed=True)
00419             cat = getToolByName(portal, 'portal_catalog', None)
00420             if cat is not None:
00421                 topics = cat(portal_type='Topic')
00422                 for b in topics:
00423                     topic = b.getObject()
00424                     # If syndication is already enabled then another nasty string
00425                     # exception gets raised in CMFDefault
00426                     if topic is not None and not syn.isSyndicationAllowed(topic):
00427                         syn.enableSyndication(topic)
00428                         out.append('Enabled syndication on %s'%b.getPath())
00429 
00430     def enableSite(self, portal):
00431         """
00432         Make the portal a Zope3 site and create a site manager.
00433         """
00434         if not ISite.providedBy(portal):
00435             make_objectmanager_site(portal)
00436         # The following event is primarily useful for setting the site hooks
00437         # during test runs.
00438         notify(SiteManagerCreatedEvent(portal))
00439 
00440     def assignTitles(self, portal, out):
00441         titles={'portal_actions':'Contains custom tabs and buttons',
00442          'portal_membership':'Handles membership policies',
00443          'portal_memberdata':'Handles the available properties on members',
00444          'portal_undo':'Defines actions and functionality related to undo',
00445          'portal_types':'Controls the available content types in your portal',
00446          'plone_utils':'Various utility methods',
00447          'portal_metadata':'Controls metadata like keywords, copyrights, etc',
00448          'portal_migration':'Upgrades to newer Plone versions',
00449          'portal_registration':'Handles registration of new users',
00450          'portal_skins':'Controls skin behaviour (search order etc)',
00451          'portal_syndication':'Generates RSS for folders',
00452          'portal_workflow':'Contains workflow definitions for your portal',
00453          'portal_url':'Methods to anchor you to the root of your Plone site',
00454          'portal_discussion':'Controls how discussions are stored',
00455          'portal_catalog':'Indexes all content in the site',
00456          'portal_factory':'Responsible for the creation of content objects',
00457          'portal_calendar':'Controls how events are shown',
00458          'portal_quickinstaller':'Allows to install/uninstall products',
00459          'portal_interface':'Allows to query object interfaces',
00460          'portal_actionicons':'Associates actions with icons',
00461          'portal_groupdata':'Handles properties on groups',
00462          'portal_groups':'Handles group related functionality',
00463          'translation_service': 'Provides access to the translation machinery',
00464          'mimetypes_registry': 'MIME types recognized by Plone',
00465          'portal_transforms': 'Handles data conversion between MIME types',
00466          }
00467 
00468         for oid in portal.objectIds():
00469             title=titles.get(oid, None)
00470             if title:
00471                 setattr(aq_get(portal, oid), 'title', title)
00472         out.append('Assigned titles to portal tools.')
00473 
00474 def importSite(context):
00475     """
00476     Import site settings.
00477     """
00478     site = context.getSite()
00479     gen = PloneGenerator()
00480     gen.enableSite(site)
00481     setSite(site)
00482 
00483 def importArchetypes(context):
00484     """
00485     Install Archetypes and it's dependencies.
00486     """
00487     # Only run step if a flag file is present (e.g. not an extension profile)
00488     if context.readDataFile('plone_archetypes.txt') is None:
00489         return
00490     site = context.getSite()
00491     gen = PloneGenerator()
00492     gen.installArchetypes(site)
00493 
00494 def importVarious(context):
00495     """
00496     Import various settings.
00497 
00498     Provisional handler that does initialization that is not yet taken
00499     care of by other handlers.
00500     """
00501     # Only run step if a flag file is present (e.g. not an extension profile)
00502     if context.readDataFile('plone_various.txt') is None:
00503         return
00504     site = context.getSite()
00505     gen = PloneGenerator()
00506     gen.installProducts(site)
00507     gen.addCacheHandlers(site)
00508     gen.addCacheForResourceRegistry(site)
00509     replace_local_role_manager(site, [])
00510 
00511 def importFinalSteps(context):
00512     """
00513     Final Plone import steps.
00514     """
00515     # Only run step if a flag file is present (e.g. not an extension profile)
00516     if context.readDataFile('plone-final.txt') is None:
00517         return
00518     out = []
00519     site = context.getSite()
00520     pprop = getToolByName(site, 'portal_properties')
00521     pmembership = getToolByName(site, 'portal_membership')
00522     gen = PloneGenerator()
00523     gen.performMigrationActions(site)
00524     gen.enableSyndication(site, out)
00525     gen.assignTitles(site, out)
00526     pmembership.memberareaCreationFlag = False
00527     gen.installDependencies(site)
00528 
00529 def importContent(context):
00530     """
00531     Final Plone content import step.
00532     """
00533     # Only run step if a flag file is present (e.g. not an extension profile)
00534     if context.readDataFile('plone-content.txt') is None:
00535         return
00536     out = []
00537     site = context.getSite()
00538     gen = PloneGenerator()
00539     gen.setupPortalContent(site)
00540 
00541 def updateWorkflowRoleMappings(context):
00542     """
00543     If an extension profile (such as the testfixture one) switches default,
00544     workflows, this import handler will make sure object security works
00545     properly.
00546     """
00547     site = context.getSite()
00548     portal_workflow = getToolByName(site, 'portal_workflow')
00549     portal_workflow.updateRoleMappings()
00550 
00551 def replace_local_role_manager(portal, out):
00552     """Installs the borg local role manager in place of the standard one from
00553     PlonePAS"""
00554     uf = getToolByName(portal, 'acl_users', None)
00555     # Make sure we have a PAS user folder
00556     if uf is not None and hasattr(aq_base(uf), 'plugins'):
00557         # Remove the original plugin if it's there
00558         if 'local_roles' in uf.objectIds():
00559             orig_lr = getattr(uf, 'local_roles')
00560             if isinstance(orig_lr, LocalRolesManager):
00561                 uf.plugins.removePluginById('local_roles')
00562                 out.append("Deactivated original 'local_roles' plugin")
00563         # Install the borg.localrole plugin if it's not already there
00564         out.append(setup_localrole_plugin(portal))