You are here: Home / Documentation / How To's / How to synchronize the Titan Services drop down menu items

How to synchronize the Titan Services drop down menu items

by nguyen — published Nov 20, 2009 02:55 PM, last modified Aug 16, 2016 10:50 AM
...which are really portal_actions in the titanservices subfolder

Our /home site is the "master" site for what should appear in the Titan Services drop down menu in our standard campus skin.

To put the exact same set of items in the Titan Services drop down menu of all our other campus skin sites, you must do the following:

  • Via the ZMI on client3 only (ie. ports 11082, 9082, 8082, etc.), go to each sites folder of every Zope.
  • In each sites folder, run the external method called ".importTitanServicesLinks".

If a sites folder does not have this external method but it exists on the same Zope in another sites folder, you can copy and paste it into the sites folder where it is missing.

If no other sites folder on the same Zope has this external method, you can grab the source for it in our SVN repo in or

  • ssh to the server
  • cd to /opt/Plone-3.2.3/zeocluster/parts/client3/Extensions
  • svn co
  • cd Scripts
  • mv ..
  • cd ..
  • rm -rf Scripts
  • In ZMI, go to the sites folder you want 
  • Add an External Method
  • ID: .importTitanServicesLinks, title leave blank, module: importTitanServicesLinks, method or function: importTitanServicesLinks

If you give it the ID ".importTitanServicesLinks" (starting with a period), the External Method will appear at the top of the page.

Here is the source as of this writing (Aug. 16, 2011):

# This external method pulls in a list of titanServicesLinks from the given url
# the format of the list should be: "%id,,,,,,,%title,,,,,,,%url_expr" with one entry per line
# it then iterates through all the plone sites in the container it is run on (should be the root zope instance)
# and using the list of links, it clears and rebuilds the portal_actions.titan_services category for each site

import urllib2
from Products.CMFCore.utils import getToolByName
from Products.CMFCore.ActionInformation import Action

URL = ''

def importTitanServicesLinks(self):
    if self.REQUEST.REMOTE_ADDR not in ALLOWED_HOSTS and 'Manager' not in self.REQUEST.AUTHENTICATED_USER.getRoles():
        return 'You do not have sufficent permissions to access this object\n'

    resultString = ''

    stream = urllib2.urlopen(URL)
    string =
    listOfActions = map(lambda x: tuple(x.split(',,,,,,,')), string.splitlines())

    if len(listOfActions) == 0 or len(listOfActions[0]) != 3 or len(listOfActions[-1]) != 3:
        resultString += 'No importable titan_services links from: %s\n\n' % URL

        resultString += 'Importing from: %s\n\n' % URL

        ploneSites = [obj for (id, obj) in self.objectItems() if (hasattr(obj, 'Type') and obj.Type() == 'Plone Site') and 
                                                                 (not hasattr(obj, 'titanservices_master_site') or not obj.titanservices_master_site)]

        if len(ploneSites) == 0:
            resultString += 'No eligible plone sites were found in this container\n'

        for ploneSite in ploneSites:
            resultString += '%s:\n' %
            resultString += ('-' * 20) + '\n'

            portal_actions = getToolByName(ploneSite, 'portal_actions', default=None)          
            if hasattr(portal_actions, 'titan_services'):
                titan_services = portal_actions['titan_services']

                for (id, title, urlExpr) in listOfActions:
                    action = Action(id=id, title=title, url_expr=urlExpr, i18n_domain='plone', permissions=('View',))
                    titan_services._setObject(id, action)
                    resultString += 'Created: %s, %s, %s\n' % (id, title, urlExpr)

                resultString += 'No titan_services action category exists\n'

            resultString += '\n'

    return resultString