def addCatalogIndexes(context):
    """
    Add indexes to portal_catalog.
    """

    setup = getToolByName(context, 'portal_setup')
    setup.runImportStepFromProfile(
        'profile-collective.salesforce.content:default', 'catalog')

    catalog = getToolByName(context, 'portal_catalog')
    indexes = catalog.indexes()
    
    wanted = (
        ('sf_object_id', 'FieldIndex', None),
    )

    added = []
    for name, meta_type, extra in wanted:
        if name not in indexes:
            catalog.addIndex(name, meta_type)
            added.append(name)
            logger.info("Added %s for field %s.", meta_type, name)
    if added:
        logger.info("Indexing new indexes %s.", ', '.join(added))
        catalog.manage_reindexIndex(ids=added)
    def __call__(self, token=None, catch_errors=False, email=None, types=[], sf_object_id=None):
        """
        Perform the synchronization.
        """
        
        # Protection:
        # Make sure the user has Manager access or has provided the sync key.
        if not getSecurityManager().checkPermission('Manage portal', self.context):
            registry = getUtility(IRegistry)
            sync_key = registry.get('collective.salesforce.content.sync_key')
            if not sync_key or token != sync_key:
                raise Unauthorized
            # become a superuser
            user = UnrestrictedUser('manager', '', ['Manager'], [])
            newSecurityManager(None, user)

        try:
            logger.info('Syncing picklists for %s' % self.context.Title())
            PicklistsFromSalesforce(self.context).queryObjects()

            logger.info('Syncing Salesforce objects for %s' 
                % self.context.Title())
            # Loop through the FTIs that include the ISalesforceObject behavior.
            for fti in self.getDexterityTypes():
                if types and not fti.__name__ in types:
                    continue
                if ISalesforceObject.__identifier__ in fti.behaviors:
                    query = self.getQueryFromType(fti, sf_object_id=sf_object_id)
                    logger.debug('SOQL: %s' % query)
                    if query:
                        results = self.getResults(query)
                        if results:
                            self.syncPloneObjects(fti, results, sf_object_id=sf_object_id)
        except:
            # If the catch_errors flag is set, we try to handle the error 
            # gracefully. This is mostly useful when using sf_sync
            # with Cron4Plone, which will try again if it gets an error.
            catch_errors = self.request.get('catch_errors', catch_errors)
            email = self.request.get('email', email)
            if catch_errors:
                message = traceback.format_exc()
                logger.error(message)
                if email:
                    # If we have an e-mail address, we try to send
                    # the traceback to that address.
                    MailHost = getToolByName(self.context, 'MailHost')
                    subject = u'Salesforce Sync Failure: %s' % self.context.Title()
                    sender = getUtility(ISiteRoot).email_from_address or email
                    try:
                        MailHost.secureSend(message, email, sender,
                            subject=subject, subtype='plain', charset='utf-8')
                    except:
                        pass
            else:
                raise

        return 'Successfully ran sync.'
 def __call__(self, catch_errors=False, email=None, types=[], sf_object_id=None):
     """
     Perform the synchronization.
     """
     
     try:
         logger.info('Syncing Salesforce objects for %s' 
             % self.context.Title())
         # Loop through the FTIs that include the ISalesforceObject behavior.
         for fti in self.getDexterityTypes():
             if types and not fti.__name__ in types:
                 continue
             if ISalesforceObject.__identifier__ in fti.behaviors:
                 query = self.getQueryFromType(fti, sf_object_id=sf_object_id)
                 logger.debug('SOQL: %s' % query)
                 if query:
                     results = self.getResults(query)
                     if results:
                         self.syncPloneObjects(fti, results, sf_object_id=sf_object_id)
     except:
         # If the catch_errors flag is set, we try to handle the error 
         # gracefully. This is mostly useful when using sf_sync
         # with Cron4Plone, which will try again if it gets an error.
         catch_errors = self.request.get('catch_errors', catch_errors)
         email = self.request.get('email', email)
         if catch_errors:
             message = traceback.format_exc()
             logger.error(message)
             if email:
                 # If we have an e-mail address, we try to send
                 # the traceback to that address.
                 MailHost = getToolByName(self.context, 'MailHost')
                 subject = u'Salesforce Sync Failure: %s' % self.context.Title()
                 sender = getUtility(ISiteRoot).email_from_address or email
                 try:
                     MailHost.secureSend(message, email, sender,
                         subject=subject, subtype='plain', charset='utf-8')
                 except:
                     pass
         else:
             raise