Back to index

plone3  3.1.7
alphas.py
Go to the documentation of this file.
00001 import os
00002 
00003 from five.localsitemanager import make_objectmanager_site
00004 from five.localsitemanager.registry import FiveVerifyingAdapterLookup
00005 from zope.app.component.interfaces import ISite
00006 from zope.component import getMultiAdapter
00007 from zope.component import getSiteManager
00008 from zope.component import getUtility
00009 
00010 from Acquisition import aq_base
00011 from Globals import package_home
00012 
00013 from Products.StandardCacheManagers import RAMCacheManager
00014 
00015 from Products.Archetypes.interfaces import IArchetypeTool
00016 from Products.Archetypes.interfaces import IReferenceCatalog
00017 from Products.Archetypes.interfaces import IUIDCatalog
00018 from Products.ATContentTypes.interface import IATCTTool
00019 from Products.ATContentTypes.migration.v1_2 import upgradeATCTTool
00020 from Products.CMFActionIcons.interfaces import IActionIconsTool
00021 from Products.CMFCalendar.interfaces import ICalendarTool
00022 from Products.CMFCore.ActionInformation import Action
00023 from Products.CMFCore.ActionInformation import ActionCategory
00024 from Products.CMFCore.Expression import Expression
00025 from Products.CMFCore.interfaces import IActionsTool
00026 from Products.CMFCore.interfaces import ICachingPolicyManager
00027 from Products.CMFCore.interfaces import ICatalogTool
00028 from Products.CMFCore.interfaces import IContentTypeRegistry
00029 from Products.CMFCore.interfaces import IDiscussionTool
00030 from Products.CMFCore.interfaces import IMemberDataTool
00031 from Products.CMFCore.interfaces import IMembershipTool
00032 from Products.CMFCore.interfaces import IMetadataTool
00033 from Products.CMFCore.interfaces import IPropertiesTool
00034 from Products.CMFCore.interfaces import IRegistrationTool
00035 from Products.CMFCore.interfaces import ISiteRoot
00036 from Products.CMFCore.interfaces import ISkinsTool
00037 from Products.CMFCore.interfaces import ISyndicationTool
00038 from Products.CMFCore.interfaces import ITypesTool
00039 from Products.CMFCore.interfaces import IUndoTool
00040 from Products.CMFCore.interfaces import IURLTool
00041 from Products.CMFCore.interfaces import IConfigurableWorkflowTool
00042 from Products.CMFCore.utils import getToolByName
00043 from Products.CMFCore.permissions import ManagePortal
00044 from Products.CMFCore.DirectoryView import createDirectoryView
00045 from Products.CMFDiffTool.interfaces import IDiffTool
00046 from Products.CMFEditions.interfaces import IArchivistTool
00047 from Products.CMFEditions.interfaces import IPortalModifierTool
00048 from Products.CMFEditions.interfaces import IPurgePolicyTool
00049 from Products.CMFEditions.interfaces.IRepository import IRepositoryTool
00050 from Products.CMFEditions.interfaces import IStorageTool
00051 from Products.CMFFormController.interfaces import IFormControllerTool
00052 from Products.CMFPlone import cmfplone_globals
00053 from Products.CMFPlone.interfaces import IControlPanel
00054 from Products.CMFPlone.interfaces import IFactoryTool
00055 from Products.CMFPlone.interfaces import IInterfaceTool
00056 from Products.CMFPlone.interfaces import IMigrationTool
00057 from Products.CMFPlone.interfaces import IPloneSiteRoot
00058 from Products.CMFPlone.interfaces import IPloneTool
00059 from Products.CMFPlone.interfaces import ITranslationServiceTool
00060 from Products.CMFPlone.migrations.migration_util import installOrReinstallProduct
00061 from Products.CMFPlone.migrations.migration_util import loadMigrationProfile
00062 from Products.CMFQuickInstallerTool.interfaces import IQuickInstallerTool
00063 from Products.CMFUid.interfaces import IUniqueIdAnnotationManagement
00064 from Products.CMFUid.interfaces import IUniqueIdGenerator
00065 from Products.CMFUid.interfaces import IUniqueIdHandler
00066 from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
00067 from Products.DCWorkflow.exportimport import WorkflowDefinitionConfigurator, _initDCWorkflow
00068 from Products.GenericSetup.interfaces import ISetupTool
00069 from Products.MailHost.interfaces import IMailHost
00070 from Products.MimetypesRegistry.interfaces import IMimetypesRegistryTool
00071 from Products.PloneLanguageTool.interfaces import ILanguageTool
00072 from Products.PlonePAS.interfaces.group import IGroupTool
00073 from Products.PlonePAS.interfaces.group import IGroupDataTool
00074 from Products.PortalTransforms.interfaces import IPortalTransformsTool
00075 from Products.ResourceRegistries.interfaces import ICSSRegistry
00076 from Products.ResourceRegistries.interfaces import IJSRegistry
00077 
00078 from plone.portlets.interfaces import IPortletManager
00079 from plone.portlets.interfaces import ILocalPortletAssignmentManager
00080 from plone.portlets.constants import CONTEXT_CATEGORY as CONTEXT_PORTLETS
00081 
00082 from plone.app.portlets.utils import convert_legacy_portlets
00083 
00084 def three0_alpha1(portal):
00085     """2.5.x -> 3.0-alpha1
00086     """
00087     out = []
00088 
00089     # Make the portal a Zope3 site
00090     enableZope3Site(portal, out)
00091 
00092     # register some tools as utilities
00093     registerToolsAsUtilities(portal, out)
00094 
00095     # Updates the available import steps, so the componentregistry step is
00096     # available for add-on product installation
00097     updateImportStepsFromBaseProfile(portal, out)
00098 
00099     # Migrate old ActionInformation to Actions and move them to the actions tool
00100     migrateOldActions(portal, out)
00101 
00102     # Add new css files to RR
00103     addNewCSSFiles(portal, out)
00104 
00105     # Add new properties for default- and forbidden content types
00106     addDefaultAndForbiddenContentTypesProperties(portal, out)
00107     addMarkupConfiglet(portal, out)
00108     addIconForMarkupConfiglet(portal, out)
00109 
00110     # Actions should gain a i18n_domain now, so their title and description are
00111     # returned as Messages
00112     updateActionsI18NDomain(portal, out)
00113 
00114     # Type information should gain a i18n_domain now, so their title and
00115     # description are returned as Messages
00116     updateFTII18NDomain(portal, out)
00117 
00118     # The ATCT tool has lost all type migration functionality and quite some
00119     # metadata and index information stored on it needs to be updated.
00120     upgradeATCTTool(portal, out)
00121 
00122     # Install CMFEditions and 
00123     installProduct('CMFDiffTool', portal, out, hidden=True)
00124     installProduct('CMFEditions', portal, out, hidden=True)
00125 
00126     # Migrate legacy portlets
00127     addPortletManagers(portal, out)
00128 
00129     # Migrate legacy portlets
00130     convertLegacyPortlets(portal, out)
00131 
00132     # Add icon for calendar settings configlet
00133     addIconForCalendarSettingsConfiglet(portal, out)
00134 
00135     # Install the calendar settings control panel
00136     addCalendarConfiglet(portal, out)
00137 
00138     # Deal with the tableless skin disappearing
00139     removeTablelessSkin(portal, out)
00140 
00141     return out
00142 
00143 def alpha1_alpha2(portal):
00144     """ 3.0-alpha1 -> 3.0-alpha2
00145     """
00146     out = []
00147 
00148     # register some tools as utilities
00149     enableZope3Site(portal, out)
00150     registerToolsAsUtilities(portal, out)
00151 
00152     # Update search and mailhost control panels to new formlib based ones
00153     updateSearchAndMailHostConfiglet(portal, out)
00154 
00155     # remove generated.css from ResourceRegistries
00156     removeGeneratedCSS(portal, out)
00157 
00158     # add form_tabbing.js
00159     addFormTabbingJS(portal, out)
00160 
00161     # install the kss bits
00162     installKss(portal, out)
00163 
00164     # install plone.app.redirector
00165     installRedirectorUtility(portal, out)
00166 
00167     # Add action for plone.app.contentrules
00168     addContentRulesAction(portal, out)
00169 
00170     # Add reader and editor roles
00171     addReaderAndEditorRoles(portal, out)
00172 
00173     # Change folder_localrole_form to @@sharing
00174     migrateLocalroleForm(portal, out)
00175 
00176     # Reorder the user actions in a way that makes the getOrderedUserActions
00177     # script obsolete
00178     reorderUserActions(portal, out)
00179 
00180     # Update expression on RTL.css
00181     updateRtlCSSexpression(portal, out)
00182 
00183     return out
00184 
00185 
00186 def alpha2_beta1(portal):
00187     """ 3.0-alpha2 -> 3.0-beta1
00188     """
00189     out = []
00190 
00191     # register some tools as utilities
00192     enableZope3Site(portal, out)
00193     registerToolsAsUtilities(portal, out)
00194 
00195     # Add control panel action 
00196     addMaintenanceConfiglet(portal, out)
00197     
00198     # Add action icon
00199     addIconForMaintenanceConfiglet(portal, out)
00200 
00201     # Add number_of_days_to_keep property
00202     addMaintenanceProperty(portal, out)
00203 
00204     installS5(portal, out)
00205     
00206     addTableContents(portal, out)
00207 
00208     # add input-label.js
00209     addFormInputLabelJS(portal, out)
00210     
00211     #modify member security settings to match new default policies
00212     updateMemberSecurity(portal, out)
00213 
00214     updatePASPlugins(portal, out)
00215     
00216     # Update control panel actions
00217     updateSkinsAndSiteConfiglet(portal, out)
00218 
00219     # Rename some control panel titles
00220     updateConfigletTitles(portal, out)
00221 
00222     # Add icon for filter and security configlets
00223     addIconsForFilterAndSecurityConfiglets(portal, out)
00224 
00225     # add content rules configlet
00226     installContentRulesUtility(portal, out)
00227     addContentRulesConfiglet(portal, out)
00228     addIconForContentRulesConfiglet(portal, out)
00229 
00230     # Install the filter and security control panels
00231     addFilterAndSecurityConfiglets(portal, out)
00232 
00233     # Add the sitemap enabled property
00234     addSitemapProperty(portal, out)
00235 
00236     # Use the unpacked kukit-src.js and pack it ourself
00237     updateKukitJS(portal, out)
00238 
00239     # Add a RAMCache for ResourceRegistries
00240     addCacheForResourceRegistry(portal, out)
00241 
00242     # Compress cssQuery with full-encode like it's supposed to.
00243     updateCssQueryJS(portal, out)
00244 
00245     # Remove very old javascript
00246     removeHideAddItemsJS(portal, out)
00247 
00248     # Add webstats.js for Google Analytics
00249     addWebstatsJSFile(portal,out)
00250     
00251     # Add webstats_js property to site properties
00252     addWebstatsJSProperty(portal,out)
00253 
00254     # Add the object_provides catalog index
00255     addObjectProvidesIndex(portal, out)
00256 
00257     # Remove the mystuff user action
00258     removeMyStuffAction(portal, out)
00259 
00260     # Add external_links_open_new_window property to site properties
00261     addExternalLinksOpenNewWindowProperty(portal, out)
00262 
00263     # Add the types configlet
00264     addTypesConfiglet(portal, out)
00265     addIconForTypesConfiglet(portal, out)
00266     
00267     # Add workflows that people may be missing
00268     addMissingWorkflows(portal, out)
00269 
00270     # Add many_groups property to site properties
00271     addManyGroupsProperty(portal, out)
00272 
00273     # Replace obsolete PlonePAS version of plone tool
00274     restorePloneTool(portal, out)
00275 
00276     # install plone.app.i18n
00277     installI18NUtilities(portal, out)
00278 
00279     # Install PloneLanguageTool
00280     installProduct('PloneLanguageTool', portal, out, hidden=True)
00281 
00282     # Add email_charset property
00283     addEmailCharsetProperty(portal, out)
00284 
00285     return out
00286 
00287 # --
00288 # KSS registration
00289 # --
00290 
00291 class installKss(object):
00292 
00293     js_unregister = []
00294 
00295     js_all = [
00296         ('++resource++MochiKit.js', 'none', False),
00297         ('++resource++prototype.js', 'safe', True),
00298         ('++resource++effects.js', 'safe', True),
00299         ('++resource++kukit.js', 'none', True),
00300     ]
00301 
00302     css_all = [
00303         'ploneKss.css',
00304     ]
00305 
00306     kss_all = [
00307         'plone.kss',
00308         'at.kss',
00309     ]
00310 
00311     def __init__(self, portal, out):
00312         self.portal = portal
00313         self.out = out
00314         self.installKss()
00315 
00316     @staticmethod
00317     def _old_res(tool, id):
00318         return tool.getResourcesDict().get(id, None)
00319      
00320     def install_resources(self):
00321         portal, out = self.portal, self.out
00322         jstool = getToolByName(portal, 'portal_javascripts')
00323         for id in self.js_unregister:
00324             if self._old_res(jstool, id):
00325                 jstool.unregisterResource(id)
00326                 out.append("Unregistered old %s" % (id, ))
00327         for id, compression, enabled in self.js_all:
00328             if not self._old_res(jstool, id):
00329                 jstool.registerScript(
00330                     id = id,
00331                     enabled = enabled,
00332                     cookable = True,
00333                     compression = compression,
00334                     )
00335         csstool = getToolByName(portal, 'portal_css')
00336         for css in self.css_all:
00337             if not self._old_res(csstool, css):
00338                 csstool.manage_addStylesheet(
00339                     id = css,
00340                     rel = 'stylesheet',
00341                     rendering = 'link',
00342                     enabled = True,
00343                     cookable = True,
00344                     )
00345         # kss stylesheets
00346         for kss in self.kss_all:
00347             if not self._old_res(csstool, kss):
00348                 csstool.manage_addStylesheet(id=kss,
00349                     rel='k-stylesheet',
00350                     rendering = 'link',
00351                     enabled=True,
00352                     cookable=False,
00353                     )
00354         out.append("Registered kss resources")
00355 
00356     def install_mimetype(self):
00357         portal, out = self.portal, self.out
00358         mt = getToolByName(portal, 'mimetypes_registry')
00359         mt.manage_addMimeType('KSS (Azax) StyleSheet', ('text/kss', ), ('kss', ), 'text.png',
00360                                binary=0, globs=('*.kss', ))
00361         out.append("Registered kss mimetype")
00362 
00363     def install_skins(self):
00364         portal, out = self.portal, self.out
00365         st = getToolByName(portal, 'portal_skins')
00366         skins = ['Plone Default', 'Plone Tableless']
00367         if not hasattr(aq_base(st), 'plone_kss'):
00368             createDirectoryView(st, 'CMFPlone/skins/plone_kss')
00369         if not hasattr(aq_base(st), 'archetypes_kss'):
00370             createDirectoryView(st, 'Archetypes/skins/archetypes_kss')
00371         selections = st._getSelections()
00372         for s in skins:
00373             if not selections.has_key(s):
00374                continue
00375             path = st.getSkinPath(s)
00376             path = [p.strip() for p in  path.split(',')]
00377             path_changed = False
00378             if not 'plone_kss' in path:
00379                 path.append('plone_kss')
00380                 path_changed = True
00381             if not 'archetypes_kss' in path:
00382                 path.append('archetypes_kss')
00383                 path_changed = True
00384             if path_changed:
00385                 st.addSkinSelection(s, ','.join(path))
00386                 out.append('Added missing skins to %s' % s)
00387 
00388     def installKss(self):
00389         out = self.out
00390         self.install_mimetype() 
00391         self.install_resources() 
00392         self.install_skins() 
00393         out.append("Succesfully migrated portal to KSS")
00394 
00395 
00396 def enableZope3Site(portal, out):
00397     if not ISite.providedBy(portal):
00398         make_objectmanager_site(portal)
00399         out.append('Made the portal a Zope3 site.')
00400     else:
00401         sm = portal.getSiteManager()
00402         if sm.utilities.LookupClass  != FiveVerifyingAdapterLookup:
00403             sm.utilities.LookupClass = FiveVerifyingAdapterLookup
00404             sm.utilities._createLookup()
00405             sm.utilities.__parent__ = aq_base(sm)
00406             sm.__parent__ = aq_base(portal)
00407 
00408 
00409 def migrateOldActions(portal, out):
00410     special_providers = ['portal_controlpanel',
00411                          'portal_types',
00412                          'portal_workflow']
00413     # We don't need to operate on the providers that are still valid and
00414     # should ignore the control panel as well
00415     providers = [obj for obj in portal.objectValues()
00416                      if hasattr(obj, '_actions') and
00417                      obj.getId() not in special_providers]
00418     non_empty_providers = [p for p in providers if len(p._actions) > 0]
00419     for provider in non_empty_providers:
00420         for action in provider._actions:
00421             category = action.category
00422             # check if the category already exists, otherwise create it
00423             new_category = getattr(aq_base(portal.portal_actions), category, None)
00424             if new_category is None:
00425                 portal.portal_actions._setObject(category, ActionCategory(id=category))
00426                 new_category = portal.portal_actions[category]
00427 
00428             # Special handling for Expressions
00429             url_expr = ''
00430             if action.action:
00431                 url_expr = action.action.text
00432             available_expr = ''
00433             if action.condition:
00434                 available_expr = action.condition.text
00435 
00436             new_action = Action(action.id,
00437                 title=action.title,
00438                 description=action.description,
00439                 url_expr=url_expr,
00440                 available_expr=available_expr,
00441                 permissions=action.permissions,
00442                 visible = action.visible)
00443                 
00444             # Only add an action if there isn't one with that name already
00445             if getattr(aq_base(new_category), action.id, None) is None:
00446                 new_category._setObject(action.id, new_action)
00447 
00448         # Remove old actions from migrated providers
00449         provider._actions = ()
00450     out.append('Migrated old actions to new actions stored in portal_actions.')
00451 
00452 
00453 def addNewCSSFiles(portal, out):
00454     # add new css files to the portal_css registries
00455     cssreg = getToolByName(portal, 'portal_css', None)
00456     stylesheet_ids = cssreg.getResourceIds()
00457     if 'navtree.css' not in stylesheet_ids:
00458         cssreg.registerStylesheet('navtree.css', media='screen')
00459         cssreg.moveResourceAfter('navtree.css', 'deprecated.css')
00460         out.append("Added navtree.css to the registry")
00461     if 'invisibles.css' not in stylesheet_ids:
00462         cssreg.registerStylesheet('invisibles.css', media='screen')
00463         cssreg.moveResourceAfter('invisibles.css', 'navtree.css')
00464         out.append("Added invisibles.css to the registry")
00465     if 'forms.css' not in stylesheet_ids:
00466         cssreg.registerStylesheet('forms.css', media='screen')
00467         cssreg.moveResourceAfter('forms.css', 'invisibles.css')
00468         out.append("Added forms.css to the registry")
00469 
00470 
00471 def addDefaultAndForbiddenContentTypesProperties(portal, out):
00472     """Adds sitewide config for default and forbidden content types for AT textfields."""
00473     propTool = getToolByName(portal, 'portal_properties', None)
00474     if propTool is not None:
00475         propSheet = getattr(aq_base(propTool), 'site_properties', None)
00476         if propSheet is not None:
00477             if not propSheet.hasProperty('default_contenttype'):
00478                 propSheet.manage_addProperty('default_contenttype', 'text/html', 'string')
00479             out.append("Added 'default_contenttype' property to site_properties.")
00480             if not propSheet.hasProperty('forbidden_contenttypes'):
00481                 propSheet.manage_addProperty('forbidden_contenttypes', [], 'lines')
00482                 propSheet.forbidden_contenttypes = (
00483                     'text/structured',
00484                     'text/x-rst',
00485                     'text/plain-pre',
00486                     'text/x-python',
00487                     'text/x-web-markdown',
00488                     'text/x-web-textile',
00489                     'text/x-web-intelligent')
00490             out.append("Added 'forbidden_contenttypes' property to site_properties.")
00491 
00492 
00493 def addMarkupConfiglet(portal, out):
00494     """Add the markup configlet."""
00495     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
00496     if controlPanel is not None:
00497         gotMarkup = False
00498         for configlet in controlPanel.listActions():
00499             if configlet.getId() == 'MarkupSettings':
00500                 gotMarkup = True
00501         if not gotMarkup:
00502             controlPanel.registerConfiglet(
00503                 id         = 'MarkupSettings',
00504                 appId      = 'Plone',
00505                 name       = 'Markup',
00506                 action     = 'string:${portal_url}/@@markup-controlpanel',
00507                 category   = 'Plone',
00508                 permission = ManagePortal,
00509             )
00510             out.append("Added Markup Settings to the control panel")
00511 
00512 
00513 def addIconForMarkupConfiglet(portal, out):
00514     """Adds an icon for the markup settings configlet. """
00515     iconsTool = getToolByName(portal, 'portal_actionicons', None)
00516     if iconsTool is not None:
00517         for icon in iconsTool.listActionIcons():
00518             if icon.getActionId() == 'MarkupSettings':
00519                 break # We already have the icon
00520         else:
00521             iconsTool.addActionIcon(
00522                 category='controlpanel',
00523                 action_id='MarkupSettings',
00524                 icon_expr='edit.gif',
00525                 title='Markup',
00526                 )
00527         out.append("Added markup configlet icon to actionicons tool.")     
00528 
00529 
00530 def addTypesConfiglet(portal, out):
00531     """Add the types configlet."""
00532     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
00533     if controlPanel is not None:
00534         gotTypes = False
00535         for configlet in controlPanel.listActions():
00536             if configlet.getId() == 'TypesSettings':
00537                 gotTypes = True
00538         if not gotTypes:
00539             controlPanel.registerConfiglet(
00540                 id         = 'TypesSettings',
00541                 appId      = 'Plone',
00542                 name       = 'Types',
00543                 action     = 'string:${portal_url}/@@types-controlpanel',
00544                 category   = 'Plone',
00545                 permission = ManagePortal,
00546             )
00547             out.append("Added Types Settings to the control panel")
00548 
00549 
00550 def addIconForTypesConfiglet(portal, out):
00551     """Adds an icon for the types settings configlet. """
00552     iconsTool = getToolByName(portal, 'portal_actionicons', None)
00553     if iconsTool is not None:
00554         for icon in iconsTool.listActionIcons():
00555             if icon.getActionId() == 'TypesSettings':
00556                 break # We already have the icon
00557         else:
00558             iconsTool.addActionIcon(
00559                 category='controlpanel',
00560                 action_id='TypesSettings',
00561                 icon_expr='document_icon.gif',
00562                 title='Types',
00563                 )
00564         out.append("Added types configlet icon to actionicons tool.")            
00565 
00566 
00567 def _check_ascii(text):
00568     try:
00569         unicode(text, 'ascii')
00570     except UnicodeDecodeError:
00571         return False
00572     return True
00573 
00574 
00575 def updateActionsI18NDomain(portal, out):
00576     actions = portal.portal_actions.listActions()
00577     domainless_actions = [a for a in actions if not a.i18n_domain]
00578     for action in domainless_actions:
00579         if _check_ascii(action.title) and _check_ascii(action.description):
00580             action.i18n_domain = 'plone'
00581     out.append('Updated actions i18n domain attribute.')
00582 
00583 
00584 def updateFTII18NDomain(portal, out):
00585     types = portal.portal_types.listTypeInfo()
00586     domainless_types = [fti for fti in types if not fti.i18n_domain]
00587     for fti in domainless_types:
00588         if _check_ascii(fti.title) and _check_ascii(fti.description):
00589             fti.i18n_domain = 'plone'
00590     out.append('Updated type informations i18n domain attribute.')
00591 
00592 
00593 def addPortletManagers(portal, out):
00594     """Add new portlets managers."""
00595     loadMigrationProfile(portal, 'profile-Products.CMFPlone.migrations:2.5-3.0a1',
00596             steps=['portlets'])
00597     
00598 
00599 def convertLegacyPortlets(portal, out):
00600     """Convert portlets defined in left_slots and right_slots at the portal
00601     root to use plone.portlets. Also block portlets in the Members folder.
00602     
00603     Note - there may be other portlets defined elsewhere. These will require
00604     manual migration from the @@manage-portlets view. This is to avoid a 
00605     full walk of the portal (i.e. waking up every single object) looking for
00606     potential left_slots/right_slots! 
00607     """
00608     convert_legacy_portlets(portal)
00609     out.append('Converted legacy portlets at the portal root')
00610     out.append('NOTE: You may need to convert other portlets manually.')
00611     out.append(' - to do so, click "manage portlets" in the relevant folder.')
00612     
00613     members = getattr(portal, 'Members', None)
00614     if members is not None:
00615         membersRightSlots = getattr(aq_base(members), 'right_slots', None)
00616         if membersRightSlots == []:
00617             rightColumn = getUtility(IPortletManager, name=u'plone.rightcolumn', context=portal)
00618             portletAssignments = getMultiAdapter((members, rightColumn,), ILocalPortletAssignmentManager)
00619             portletAssignments.setBlacklistStatus(CONTEXT_PORTLETS, True)
00620             out.append('Blacklisted contextual portlets in the Members folder')
00621 
00622 
00623 def installProduct(product, portal, out, hidden=False):
00624     """Quickinstalls a product if it is not installed yet."""
00625     if product in portal.Control_Panel.Products.objectIds():
00626         installOrReinstallProduct(portal, product, out, hidden=hidden)
00627 
00628 
00629 def addIconForCalendarSettingsConfiglet(portal, out):
00630     """Adds an icon for the calendar settings configlet. """
00631     iconsTool = getToolByName(portal, 'portal_actionicons', None)
00632     if iconsTool is not None:
00633         for icon in iconsTool.listActionIcons():
00634             if icon.getActionId() == 'CalendarSettings':
00635                 break # We already have the icon
00636         else:
00637             iconsTool.addActionIcon(
00638                 category='controlpanel',
00639                 action_id='CalendarSettings',
00640                 icon_expr='event_icon.gif',
00641                 title='Calendar Settings',
00642                 )
00643         out.append("Added 'calendar' icon to actionicons tool.")
00644 
00645 
00646 def addCalendarConfiglet(portal, out):
00647     """Add the configlet for the calendar settings"""
00648     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
00649     if controlPanel is not None:
00650         haveCalendar = False
00651         for configlet in controlPanel.listActions():
00652             if configlet.getId() == 'CalendarSettings':
00653                 haveCalendar = True
00654         if not haveCalendar:
00655             controlPanel.registerConfiglet(id         = 'CalendarSettings',
00656                                            appId      = 'Plone',
00657                                            name       = 'Calendar',
00658                                            action     = 'string:${portal_url}/@@calendar-controlpanel',
00659                                            category   = 'Plone',
00660                                            permission = ManagePortal,)
00661             out.append("Added calendar settings to the control panel")
00662 
00663 
00664 def updateSearchAndMailHostConfiglet(portal, out):
00665     """Use new configlets for the search and mailhost settings"""
00666     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
00667     if controlPanel is not None:
00668         search = controlPanel.getActionObject('Plone/SearchSettings')
00669         mail = controlPanel.getActionObject('Plone/MailHost')
00670 
00671         if search is not None:
00672             search.title = "Search"
00673             search.action = Expression('string:${portal_url}/@@search-controlpanel')
00674         if mail is not None:
00675             mail.title = "Mail"
00676             mail.action = Expression('string:${portal_url}/@@mail-controlpanel')
00677 
00678 
00679 def removeGeneratedCSS(portal, out):
00680     # remove generated.css from the portal_css registries
00681     cssreg = getToolByName(portal, 'portal_css', None)
00682     stylesheet_ids = cssreg.getResourceIds()
00683     if 'generated.css' in stylesheet_ids:
00684         cssreg.unregisterResource('generated.css')
00685         out.append("Removed generated.css from the registry")
00686 
00687 
00688 def addFormTabbingJS(portal, out):
00689     """Add form_tabbing.js to ResourceRegistries.
00690     """
00691     jsreg = getToolByName(portal, 'portal_javascripts', None)
00692     script = 'form_tabbing.js'
00693     if jsreg is not None:
00694         script_ids = jsreg.getResourceIds()
00695         # Failsafe: first make sure the stylesheet doesn't exist in the list
00696         if script not in script_ids:
00697             jsreg.registerScript(script)
00698             try:
00699                 jsreg.moveResourceAfter(script, 'collapsiblesections.js')
00700             except ValueError:
00701                 # put it at the bottom of the stack
00702                 jsreg.moveResourceToBottom(script)
00703             out.append("Added " + script + " to portal_javascipt")
00704 
00705 
00706 def addFormInputLabelJS(portal, out):
00707     """Add input-label.js to ResourceRegistries.
00708     """
00709     jsreg = getToolByName(portal, 'portal_javascripts', None)
00710     script = 'input-label.js'
00711     if jsreg is not None:
00712         script_ids = jsreg.getResourceIds()
00713         # Failsafe: first make sure the stylesheet doesn't exist in the list
00714         if script not in script_ids:
00715             jsreg.registerScript(script)
00716             out.append("Added " + script + " to portal_javascipt")
00717 
00718 
00719 registration = (('mimetypes_registry', IMimetypesRegistryTool),
00720                 ('portal_transforms', IPortalTransformsTool),
00721                 ('portal_atct', IATCTTool),
00722                 ('portal_actionicons', IActionIconsTool),
00723                 ('portal_discussion', IDiscussionTool),
00724                 ('portal_metadata', IMetadataTool),
00725                 ('portal_properties', IPropertiesTool),
00726                 ('portal_syndication', ISyndicationTool),
00727                 ('portal_undo', IUndoTool),
00728                 ('portal_interface', IInterfaceTool),
00729                 ('portal_migration', IMigrationTool),
00730                 ('MailHost', IMailHost),
00731                 ('portal_diff', IDiffTool),
00732                 ('portal_uidannotation', IUniqueIdAnnotationManagement),
00733                 ('portal_uidgenerator', IUniqueIdGenerator),
00734                )
00735 
00736 invalid_regs = (ILanguageTool, IArchivistTool, IPortalModifierTool,
00737                 IPurgePolicyTool, IRepositoryTool, IStorageTool,
00738                 IFormControllerTool, IReferenceCatalog, IUIDCatalog,
00739                 ICalendarTool, IActionsTool, ICatalogTool,
00740                 IContentTypeRegistry, ISkinsTool, ITypesTool, IURLTool,
00741                 IConfigurableWorkflowTool, IPloneTool, ICSSRegistry,
00742                 IJSRegistry, IUniqueIdHandler, IFactoryTool, IMembershipTool,
00743                 IGroupTool, IGroupDataTool, IMemberDataTool,
00744                 ICachingPolicyManager, IRegistrationTool, IArchetypeTool,
00745                 ITranslationServiceTool, IControlPanel, IQuickInstallerTool,
00746                 ISetupTool,
00747                )
00748 
00749 def registerToolsAsUtilities(portal, out):
00750     sm = getSiteManager(portal)
00751 
00752     portalregistration = ((portal, ISiteRoot),
00753                           (portal, IPloneSiteRoot),)
00754 
00755     for reg in portalregistration:
00756         if sm.queryUtility(reg[1]) is None:
00757             sm.registerUtility(aq_base(reg[0]), reg[1])
00758 
00759     for reg in registration:
00760         if sm.queryUtility(reg[1]) is None:
00761             if reg[0] in portal.keys():
00762                 tool = aq_base(portal[reg[0]])
00763                 sm.registerUtility(tool, reg[1])
00764 
00765     for reg in invalid_regs:
00766         if sm.queryUtility(reg) is not None:
00767             sm.unregisterUtility(provided=reg)
00768 
00769     out.append("Registered tools as utilities.")
00770 
00771 
00772 def installRedirectorUtility(portal, out):
00773     from plone.app.redirector.interfaces import IRedirectionStorage
00774     from plone.app.redirector.storage import RedirectionStorage
00775     
00776     sm = getSiteManager(portal)
00777     if sm.queryUtility(IRedirectionStorage) is None:
00778         sm.registerUtility(RedirectionStorage(), IRedirectionStorage)
00779 
00780     out.append("Registered redirector utility")
00781 
00782 
00783 def addContentRulesAction(portal, out):
00784     portal_actions = getToolByName(portal, 'portal_actions', None)
00785     if portal_actions is not None:
00786         object_category = getattr(portal_actions, 'object', None)
00787         if object_category is not None:
00788             if 'contentrules' not in object_category.objectIds():
00789                 new_action = Action('contentrules',
00790                                     title='Rules',
00791                                     description='',
00792                                     url_expr='string:${plone_context_state/canonical_object_url}/@@manage-content-rules',
00793                                     available_expr="python:plone_context_state.canonical_object().restrictedTraverse('@@plone_interface_info').provides('plone.contentrules.engine.interfaces.IRuleAssignable')",
00794                                     permissions='Content rules: Manage rules',
00795                                     visible=True)
00796                 object_category._setObject('contentrules', new_action)
00797                 out.append("Added content rules action to object category")
00798 
00799 
00800 def installContentRulesUtility(portal, out):
00801     from plone.contentrules.engine.interfaces import IRuleStorage
00802     from plone.contentrules.engine.storage import RuleStorage
00803     
00804     sm = getSiteManager(portal)
00805     if sm.queryUtility(IRuleStorage) is None:
00806         sm.registerUtility(RuleStorage(), IRuleStorage)
00807 
00808     out.append("Registered content rules storage utility")
00809 
00810 
00811 def addReaderAndEditorRoles(portal, out):
00812     if 'Reader' not in portal.valid_roles():
00813         portal._addRole('Reader')
00814     if 'Editor' not in portal.valid_roles():
00815         portal._addRole('Editor')
00816     if 'Reader' not in portal.acl_users.portal_role_manager.listRoleIds():
00817         portal.acl_users.portal_role_manager.addRole('Reader')
00818     if 'Editor' not in portal.acl_users.portal_role_manager.listRoleIds():
00819         portal.acl_users.portal_role_manager.addRole('Editor')
00820     
00821     viewRoles = [r['name'] for r in portal.rolesOfPermission('View') if r['selected']]
00822     modifyRoles = [r['name'] for r in portal.rolesOfPermission('Modify portal content') if r['selected']]
00823     
00824     if 'Reader' not in viewRoles:
00825         viewRoles.append('Reader')
00826         portal.manage_permission('View', viewRoles, True)
00827         
00828     if 'Editor' not in modifyRoles:
00829         modifyRoles.append('Editor')
00830         portal.manage_permission('Modify portal content', modifyRoles, True)
00831 
00832     out.append('Added reader and editor roles')
00833 
00834 
00835 def migrateLocalroleForm(portal, out):
00836     portal_types = getToolByName(portal, 'portal_types', None)
00837     if portal_types is not None:
00838         for fti in portal_types.objectValues():
00839             if not hasattr(fti, '_aliases'):
00840                 fti._aliases={}
00841             
00842             aliases = fti.getMethodAliases()
00843             new_aliases = aliases.copy()
00844             for k, v in aliases.items():
00845                 if 'folder_localrole_form' in v:
00846                     new_aliases[k] = v.replace('folder_localrole_form', '@@sharing')
00847             fti.setMethodAliases(new_aliases)
00848             
00849             for a in fti.listActions():
00850                 expr = a.getActionExpression()
00851                 if 'folder_localrole_form' in expr:
00852                     a.setActionExpression(expr.replace('folder_localrole_form', '@@sharing'))
00853     out.append('Ensured references to folder_localrole_form point to @@sharing now')
00854 
00855 
00856 def reorderUserActions(portal, out):
00857     portal_actions = getToolByName(portal, 'portal_actions', None)
00858     if portal_actions is not None:
00859         user_category = getattr(portal_actions, 'user', None)
00860         if user_category is not None:        
00861             new_actions = ['login', 'join', 'mystuff', 'preferences', 'undo', 'logout']
00862             new_actions.reverse()
00863             for action in new_actions:
00864                 if action in user_category.objectIds():
00865                     user_category.moveObjectsToTop([action])
00866 
00867 
00868 def updateRtlCSSexpression(portal, out):
00869     # update expression on rtl css file
00870     cssreg = getToolByName(portal, 'portal_css', None)
00871     if cssreg is not None:
00872         stylesheet_ids = cssreg.getResourceIds()
00873         if 'RTL.css' in stylesheet_ids:
00874             rtl = cssreg.getResource('RTL.css')
00875             rtl.setExpression("python:portal.restrictedTraverse('@@plone_portal_state').is_rtl()")
00876             out.append("Updated RTL.css expression.")
00877 
00878 
00879 def installS5(portal, out):
00880     portalTypes = getToolByName(portal, 'portal_types', None)
00881     if portalTypes is not None:
00882         document = portalTypes.restrictedTraverse('Document', None)
00883         if document:
00884             for action in document.listActions():
00885                 if action.getId() == 's5_presentation':
00886                     break # We already have the action
00887             else:
00888                 document.addAction('s5_presentation',
00889                     name='View as presentation',
00890                     action="string:${object/absolute_url}/document_s5_presentation",
00891                     condition='python:object.document_s5_alter(test=True)',
00892                     permission='View',
00893                     category='document_actions',
00894                     visible=1,
00895                     )
00896             out.append("Added 's5_presentation' action to actions tool.")
00897 
00898     iconsTool = getToolByName(portal, 'portal_actionicons', None)
00899     if iconsTool is not None:
00900         for icon in iconsTool.listActionIcons():
00901             if icon.getActionId() == 's5_presentation':
00902                 break # We already have the icon
00903         else:
00904             iconsTool.addActionIcon(
00905                 category='plone',
00906                 action_id='s5_presentation',
00907                 icon_expr='fullscreenexpand_icon.gif',
00908                 title='View as presentation',
00909                 )
00910         out.append("Added 's5_presentation' icon to actionicons tool.")
00911 
00912 
00913 def addIconForMaintenanceConfiglet(portal, out):
00914     """Adds an icon for the maintenance settings configlet. """
00915     iconsTool = getToolByName(portal, 'portal_actionicons', None)
00916     if iconsTool is not None:
00917         for icon in iconsTool.listActionIcons():
00918             if icon.getActionId() == 'Maintenance':
00919                 break # We already have the icon
00920         else:
00921             iconsTool.addActionIcon(
00922                 category='controlpanel',
00923                 action_id='Maintenance',
00924                 icon_expr='maintenance_icon.gif',
00925                 title='Maintenance',
00926                 )
00927         out.append("Added 'maintenance' icon to actionicons tool.")
00928 
00929 
00930 def addMaintenanceConfiglet(portal, out):
00931     """Add the configlet for the calendar settings"""
00932     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
00933     if controlPanel is not None:
00934         havePanel = False
00935         for configlet in controlPanel.listActions():
00936             if configlet.getId() == 'Maintenance':
00937                 havePanel = True
00938         if not havePanel:
00939             controlPanel.registerConfiglet(id         = 'Maintenance',
00940                                            appId      = 'Plone',
00941                                            name       = 'Maintenance',
00942                                            action     = 'string:${portal_url}/@@maintenance-controlpanel',
00943                                            category   = 'Plone',
00944                                            permission = ManagePortal,)
00945             out.append("Added 'Maintenance' to the control panel")
00946 
00947 
00948 def addMaintenanceProperty(portal, out):
00949     """ adds a site property to portal_properties"""
00950     tool = getToolByName(portal, 'portal_properties', None)
00951     if tool is not None:
00952         sheet = getattr(tool, 'site_properties', None)
00953         if sheet is not None:
00954             if not sheet.hasProperty('number_of_days_to_keep'):
00955                 sheet.manage_addProperty('number_of_days_to_keep', 7, 'int')
00956                 out.append("Added 'number_of_days_to_keep' property to site properties")
00957 
00958 
00959 def addWebstatsJSProperty(portal, out):
00960     """ adds a site property to portal_properties"""
00961     tool = getToolByName(portal, 'portal_properties')
00962     sheet = tool.site_properties
00963     if not sheet.hasProperty('webstats_js'):
00964         sheet.manage_addProperty('webstats_js','','string')
00965         out.append("Added 'webstats_js' property to site properties")
00966 
00967 
00968 def addLinkIntegritySwitch(portal, out):
00969     """ adds a site property to portal_properties """
00970     tool = getToolByName(portal, 'portal_properties', None)
00971     if tool is not None:
00972         sheet = getattr(tool, 'site_properties', None)
00973         if sheet is not None:
00974             if not sheet.hasProperty('enable_link_integrity_checks'):
00975                 sheet.manage_addProperty('enable_link_integrity_checks', True, 'boolean')
00976                 out.append("Added 'enable_link_integrity_checks' property to site properties")
00977 
00978 
00979 def addWebstatsJSFile(portal, out):
00980     """Add webstats.js for Google Analytics and other trackers support.
00981     """
00982     jsreg = getToolByName(portal, 'portal_javascripts', None)
00983     script = 'webstats.js'
00984     if jsreg is not None:
00985         script_ids = jsreg.getResourceIds()
00986         # Failsafe: first make sure the stylesheet doesn't exist in the list
00987         if script not in script_ids:
00988             jsreg.registerScript(script,
00989                     enabled = True,
00990                     cookable = True,
00991                     compression = False)
00992             try:
00993                 jsreg.moveResourceAfter(script, 'toc.js')
00994             except ValueError:
00995                 # put it at the bottom of the stack
00996                 jsreg.moveResourceToBottom(script)
00997             out.append("Added " + script + " to portal_javascipts")
00998 
00999 
01000 def addTableContents(portal, out):
01001     """ Adds in table of contents """
01002     csstool = getToolByName(portal, "portal_css", None)
01003     if csstool is not None:
01004         if 'toc.css' not in csstool.getResourceIds():
01005             csstool.manage_addStylesheet(id="toc.css",rel="stylesheet", enabled=True)
01006     jstool = getToolByName(portal, "portal_javascripts", None)
01007     if jstool is not None:
01008         if 'toc.js' not in jstool.getResourceIds():
01009             jstool.registerScript(id="toc.js", enabled=True)
01010     out.append("Added in css and js for table of contents")
01011 
01012 
01013 def updateMemberSecurity(portal, out):
01014     pprop = getToolByName(portal, 'portal_properties')
01015     portal.manage_permission('Add portal member', roles=['Manager','Owner'], acquire=0)
01016     pprop.site_properties.manage_changeProperties(allowAnonymousViewAbout=False)
01017 
01018     portal.manage_changeProperties(validate_email=True)
01019 
01020     pmembership = getToolByName(portal, 'portal_membership')
01021     pmembership.memberareaCreationFlag = 0
01022     out.append("Updated member management security")
01023 
01024 
01025 def updatePASPlugins(portal, out):
01026     from Products.PlonePAS.Extensions.Install import activatePluginInterfaces
01027     from StringIO import StringIO
01028 
01029     sout=StringIO()
01030 
01031     activatePluginInterfaces(portal, 'mutable_properties', sout)
01032     activatePluginInterfaces(portal, 'source_users', sout)
01033     activatePluginInterfaces(portal, 'credentials_cookie_auth', sout,
01034             disable=['ICredentialsResetPlugin', 'ICredentialsUpdatePlugin'])
01035     if not portal.acl_users.objectIds(['Plone Session Plugin']):
01036         from plone.session.plugins.session import manage_addSessionPlugin
01037         manage_addSessionPlugin(portal.acl_users, 'session')
01038         activatePluginInterfaces(portal, "session", sout)
01039         out.append("Added Plone Session Plugin.")
01040 
01041 
01042 def updateSkinsAndSiteConfiglet(portal, out):
01043     """Use new configlets for the skins and site settings"""
01044     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
01045     if controlPanel is not None:
01046         skins = controlPanel.getActionObject('Plone/PortalSkin')
01047         site = controlPanel.getActionObject('Plone/PloneReconfig')
01048 
01049         if skins is not None:
01050             skins.action = Expression('string:${portal_url}/@@skins-controlpanel')
01051             skins.title = "Themes"
01052         if site is not None:
01053             site.action = Expression('string:${portal_url}/@@site-controlpanel')
01054             site.title = "Site settings"
01055 
01056 
01057 def updateConfigletTitles(portal, out):
01058     """Update titles of some configlets"""
01059     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
01060     if controlPanel is not None:
01061         collection = controlPanel.getActionObject('Plone/portal_atct')
01062         language = controlPanel.getActionObject('Plone/PloneLanguageTool')
01063         navigation = controlPanel.getActionObject('Plone/NavigationSettings')
01064         types = controlPanel.getActionObject('Plone/TypesSettings')
01065         users = controlPanel.getActionObject('Plone/UsersGroups')
01066         users2 = controlPanel.getActionObject('Plone/UsersGroups2')
01067 
01068         if collection is not None:
01069             collection.title = "Collection"
01070         if language is not None:
01071             language.title = "Language"
01072         if navigation is not None:
01073             navigation.title = "Navigation"
01074         if types is not None:
01075             types.title = "Types"
01076         if users is not None:
01077             users.title = "Users and Groups"
01078         if users2 is not None:
01079             users2.title = "Users and Groups"
01080 
01081 
01082 def addIconsForFilterAndSecurityConfiglets(portal, out):
01083     """Adds icons for the filter and security configlets."""
01084     iconsTool = getToolByName(portal, 'portal_actionicons', None)
01085     filterIcon = False
01086     securityIcon = False
01087     if iconsTool is not None:
01088         for icon in iconsTool.listActionIcons():
01089             if icon.getActionId() == 'HtmlFilter':
01090                 filterIcon = True
01091             if icon.getActionId() == 'SecuritySettings':
01092                 securityIcon = True
01093         if not filterIcon:
01094             iconsTool.addActionIcon(
01095                 category='controlpanel',
01096                 action_id='HtmlFilter',
01097                 icon_expr='htmlfilter_icon.gif',
01098                 title='Html Filter Settings',
01099                 )
01100             out.append("Added 'filter' icon to actionicons tool.")
01101         if not securityIcon:
01102             iconsTool.addActionIcon(
01103                 category='controlpanel',
01104                 action_id='SecuritySettings',
01105                 icon_expr='lock_icon.gif',
01106                 title='Security Settings',
01107                 )
01108             out.append("Added 'security' icon to actionicons tool.")
01109 
01110 
01111 def addFilterAndSecurityConfiglets(portal, out):
01112     """Add the configlets for the filter and security settings"""
01113     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
01114     if controlPanel is not None:
01115         haveFilter = False
01116         haveSecurity = False
01117         for configlet in controlPanel.listActions():
01118             if configlet.getId() == 'HtmlFilter':
01119                 haveFilter = True
01120             if configlet.getId() == 'SecuritySettings':
01121                 haveSecurity = True
01122         if not haveFilter:
01123             controlPanel.registerConfiglet(id         = 'HtmlFilter',
01124                                            appId      = 'Plone',
01125                                            name       = 'HTML Filtering',
01126                                            action     = 'string:${portal_url}/@@filter-controlpanel',
01127                                            category   = 'Plone',
01128                                            permission = ManagePortal,)
01129             out.append("Added html filter settings to the control panel")
01130         if not haveSecurity:
01131             controlPanel.registerConfiglet(id         = 'SecuritySettings',
01132                                            appId      = 'SecuritySettings',
01133                                            name       = 'Security',
01134                                            action     = 'string:${portal_url}/@@security-controlpanel',
01135                                            category   = 'Plone',
01136                                            permission = ManagePortal,)
01137             out.append("Added security settings to the control panel")
01138 
01139 
01140 def addSitemapProperty(portal, out):
01141     tool = getToolByName(portal, 'portal_properties', None)
01142     if tool is not None:
01143         sheet = getattr(tool, 'site_properties', None)
01144         if sheet is not None:
01145             if not sheet.hasProperty('enable_sitemap'):
01146                 sheet.manage_addProperty('enable_sitemap', False, 'boolean')
01147                 out.append("Added 'enable_sitemap' property to site properties")
01148 
01149 
01150 def updateKukitJS(portal, out):
01151     """Use the unpacked kukit-src.js and pack it ourself.
01152     """
01153     jsreg = getToolByName(portal, 'portal_javascripts', None)
01154     old_id = '++resource++kukit.js'
01155     new_id = '++resource++kukit-src.js'
01156     if jsreg is not None:
01157         script_ids = jsreg.getResourceIds()
01158         if old_id in script_ids and new_id in script_ids:
01159             jsreg.unregisterResource(old_id)
01160         elif old_id in script_ids:
01161             jsreg.renameResource(old_id, new_id)
01162             out.append("Use %s instead of %s" % (new_id, old_id))
01163         resource = jsreg.getResource(new_id)
01164         if resource is not None:
01165             resource.setCompression('full')
01166             out.append("Set 'full' compression on %s" % new_id)
01167 
01168 
01169 def addCacheForResourceRegistry(portal, out):
01170     ram_cache_id = 'ResourceRegistryCache'
01171     if not ram_cache_id in portal.objectIds():
01172         RAMCacheManager.manage_addRAMCacheManager(portal, ram_cache_id)
01173         cache = getattr(portal, ram_cache_id)
01174         settings = cache.getSettings()
01175         settings['max_age'] = 24*3600 # keep for up to 24 hours
01176         settings['request_vars'] = ('URL',)
01177         cache.manage_editProps('Cache for saved ResourceRegistry files', settings)
01178         out.append('Created RAMCache %s for ResourceRegistry output' % ram_cache_id)
01179     reg = getToolByName(portal, 'portal_css', None)
01180     if reg is not None and getattr(aq_base(reg), 'ZCacheable_setManagerId', None) is not None:
01181         reg.ZCacheable_setManagerId(ram_cache_id)
01182         reg.ZCacheable_setEnabled(1)
01183         out.append('Associated portal_css with %s' % ram_cache_id)
01184     reg = getToolByName(portal, 'portal_javascripts', None)
01185     if reg is not None and getattr(aq_base(reg), 'ZCacheable_setManagerId', None) is not None:
01186         reg.ZCacheable_setManagerId(ram_cache_id)
01187         reg.ZCacheable_setEnabled(1)
01188         out.append('Associated portal_javascripts with %s' % ram_cache_id)
01189 
01190 
01191 def removeTablelessSkin(portal, out):
01192     st = getToolByName(portal, 'portal_skins')
01193     if 'Plone Tableless' in st.getSkinSelections():
01194         st.manage_skinLayers(['Plone Tableless'], del_skin=True)
01195         out.append("Removed the Plone Tableless skin")
01196     if st.default_skin=='Plone Tableless':
01197         st.default_skin='Plone Default'
01198         out.append("Changed the default skin to 'Plone Default'")
01199 
01200 
01201 def updateCssQueryJS(portal, out):
01202     """Compress cssQuery with full-encode like it's supposed to.
01203     """
01204     jsreg = getToolByName(portal, 'portal_javascripts', None)
01205     script_id = 'cssQuery.js'
01206     if jsreg is not None:
01207         script_ids = jsreg.getResourceIds()
01208         resource = jsreg.getResource(script_id)
01209         if resource is not None:
01210             resource.setCompression('full-encode')
01211             out.append("Set 'full-encode' compression on %s" % script_id)
01212 
01213 
01214 def removeHideAddItemsJS(portal, out):
01215     """Remove very old javascript.
01216     """
01217     jsreg = getToolByName(portal, 'portal_javascripts', None)
01218     script_id = 'folder_contents_hideAddItems.js'
01219     if jsreg is not None:
01220         jsreg.unregisterResource(script_id)
01221         out.append('Removed %s from portal_javascripts.' % script_id)
01222 
01223 
01224 def addContentRulesConfiglet(portal, out):
01225     """Add the configlet for the contentrules settings"""
01226     controlPanel = getToolByName(portal, 'portal_controlpanel', None)
01227     if controlPanel is not None:
01228         haveContentRules = False
01229         for configlet in controlPanel.listActions():
01230             if configlet.getId() == 'ContentRulesSettings':
01231                 haveContentRules = True
01232         if not haveContentRules:
01233             controlPanel.registerConfiglet(id         = 'ContentRules',
01234                                            appId      = 'Plone',
01235                                            name       = 'Content Rules',
01236                                            action     = 'string:${portal_url}/@@rules-controlpanel',
01237                                            category   = 'Plone',
01238                                            permission = 'Content rules: Manage rules',)
01239             out.append("Added 'Content Rules Settings' to the control panel")
01240 
01241 
01242 def addIconForContentRulesConfiglet(portal, out):
01243     """Adds an icon for the maintenance settings configlet. """
01244     iconsTool = getToolByName(portal, 'portal_actionicons', None)
01245     if iconsTool is not None:
01246         for icon in iconsTool.listActionIcons():
01247             if icon.getActionId() == 'ContentRules':
01248                 break # We already have the icon
01249         else:
01250             iconsTool.addActionIcon(
01251                 category='controlpanel',
01252                 action_id='ContentRules',
01253                 icon_expr='contentrules_icon.gif',
01254                 title='Content Rules',
01255                 )
01256         out.append("Added 'Content Rules Settings' icon to actionicons tool.")
01257 
01258 
01259 def addObjectProvidesIndex(portal, out):
01260     """Add the object_provides index to the portal_catalog.
01261     """
01262     catalog = getToolByName(portal, 'portal_catalog')
01263     if 'object_provides' not in catalog.indexes():
01264         catalog.addIndex('object_provides', 'KeywordIndex')
01265         out.append("Added object_provides index to portal_catalog")
01266 
01267 
01268 def removeMyStuffAction(portal, out):
01269     """The mystuff action is now covered by the dashboard"""
01270     actions = getToolByName(portal, 'portal_actions')
01271     if not hasattr(actions, 'user'):
01272         return
01273     category=actions.user
01274     if 'mystuff' in category.objectIds():
01275         category.manage_delObjects(ids=['mystuff'])
01276         out.append("Removed the mystuff user action")
01277 
01278 
01279 def addExternalLinksOpenNewWindowProperty(portal, out):
01280     """ adds a site property to portal_properties"""
01281     tool = getToolByName(portal, 'portal_properties')
01282     sheet = tool.site_properties
01283     if not sheet.hasProperty('external_links_open_new_window'):
01284         sheet.manage_addProperty('external_links_open_new_window','false','string')
01285         out.append("Added 'external_links_open_new_window' property to site properties")
01286 
01287 
01288 def addMissingWorkflows(portal, out):
01289     """Add new Plone 3.0 workflows
01290     """
01291     wft = getToolByName(portal, 'portal_workflow', None)
01292     if wft is None:
01293         return
01294 
01295     new_workflow_ids = [ 'intranet_workflow', 'intranet_folder_workflow',
01296                         'one_state_workflow', 'simple_publication_workflow']
01297     encoding = 'utf-8'
01298     path_prefix = os.path.join(package_home(cmfplone_globals), 'profiles',
01299             'default', 'workflows')
01300     
01301     for wf_id in new_workflow_ids:
01302         if wf_id in wft.objectIds():
01303             out.append("Workflow %s already installed; doing nothing" % wf_id)
01304             continue
01305 
01306         path = os.path.join(path_prefix, wf_id, 'definition.xml')
01307         body = open(path,'r').read()
01308 
01309         wft._setObject(wf_id, DCWorkflowDefinition(wf_id))
01310         wf = wft[wf_id]
01311         wfdc = WorkflowDefinitionConfigurator(wf)
01312 
01313         ( workflow_id
01314         , title
01315         , state_variable
01316         , initial_state
01317         , states
01318         , transitions
01319         , variables
01320         , worklists
01321         , permissions
01322         , scripts
01323         , description
01324         ) = wfdc.parseWorkflowXML(body, encoding)
01325 
01326         _initDCWorkflow( wf
01327                        , title
01328                        , description
01329                        , state_variable
01330                        , initial_state
01331                        , states
01332                        , transitions
01333                        , variables
01334                        , worklists
01335                        , permissions
01336                        , scripts
01337                        , portal     # not sure what to pass here
01338                                     # the site or the wft?
01339                                     # (does it matter at all?)
01340                       )
01341         out.append("Added workflow %s" % wf_id)
01342 
01343 
01344 def addManyGroupsProperty(portal, out):
01345     """ adds a site property to portal_properties"""
01346     tool = getToolByName(portal, 'portal_properties')
01347     sheet = tool.site_properties
01348     if not sheet.hasProperty('many_groups'):
01349         sheet.manage_addProperty('many_groups',
01350                 getattr(sheet, 'many_users', False) ,'boolean')
01351         out.append("Added 'many_groups' property to site properties")
01352 
01353 
01354 def restorePloneTool(portal, out):
01355     tool = getToolByName(portal, "plone_utils")
01356     if tool.meta_type == 'PlonePAS Utilities Tool':
01357         from Products.CMFPlone.PloneTool import PloneTool
01358         from Products.CMFDefault.Portal import CMFSite
01359 
01360         # PloneSite has its own security check for manage_delObjects which
01361         # breaks in the test runner. So we bypass this check.
01362         CMFSite.manage_delObjects(portal, ['plone_utils'])
01363         portal._setObject(PloneTool.id, PloneTool())
01364         out.append("Replaced obsolete PlonePAS version of plone tool with the normal one.")
01365 
01366 
01367 def updateImportStepsFromBaseProfile(portal, out):
01368     """Updates the available import steps for existing sites."""
01369 
01370     tool = getToolByName(portal, "portal_setup")
01371     tool.setBaselineContext("profile-Products.CMFPlone:plone")
01372 
01373 
01374 def installI18NUtilities(portal, out):
01375     from plone.app.i18n.locales.interfaces import ICountries
01376     from plone.app.i18n.locales.countries import Countries
01377 
01378     from plone.app.i18n.locales.interfaces import IContentLanguages
01379     from plone.app.i18n.locales.languages import ContentLanguages
01380 
01381     from plone.app.i18n.locales.interfaces import IMetadataLanguages
01382     from plone.app.i18n.locales.languages import MetadataLanguages
01383 
01384     sm = getSiteManager(portal)
01385     if sm.queryUtility(ICountries) is None:
01386         sm.registerUtility(Countries(), ICountries)
01387     if sm.queryUtility(IContentLanguages) is None:
01388         sm.registerUtility(ContentLanguages(), IContentLanguages)
01389     if sm.queryUtility(IMetadataLanguages) is None:
01390         sm.registerUtility(MetadataLanguages(), IMetadataLanguages)
01391 
01392     out.append("Registered plone.app.i18n utilities.")
01393 
01394 
01395 def addEmailCharsetProperty(portal, out):
01396     # Add email_charset property
01397     if not portal.hasProperty('email_charset'):
01398         portal.manage_addProperty('email_charset', 'utf-8', 'string')
01399     out.append("Added 'email_charset' property to the portal.")