コード例 #1
0
class ExternalizeLinkSettingsControlPanelEditForm(controlpanel.RegistryEditForm
                                                  ):
    """Settings form for collective.externalizelink
    """
    schema = IExternalizeLinkSettings
    id = "ExternalizeLinkSettingsEditForm"
    label = _(u"Externalize links settings")
    description = _(
        u"help_externalize_link_settings_editform",
        default=u"Site configuration for the collective.externalizelink add-on"
    )

    @button.buttonAndHandler(pmf('Save'), name='save')
    def handleSave(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return
        self.applyChanges(data)
        IStatusMessage(self.request).addStatusMessage(_(u"Changes saved"),
                                                      "info")
        self.context.REQUEST.RESPONSE.redirect("@@externalizelink-settings")

    @button.buttonAndHandler(pmf('Cancel'), name='cancel')
    def handleCancel(self, action):
        IStatusMessage(self.request).addStatusMessage(_(u"Edit cancelled"),
                                                      "info")
        self.request.response.redirect(
            "%s/%s" % (self.context.absolute_url(), self.control_panel_view))

    def updateWidgets(self):
        super(ExternalizeLinkSettingsControlPanelEditForm,
              self).updateWidgets()
        self.widgets['links_selection'].rows = 5
コード例 #2
0
    def __call__(self):
        form = self.request.form
        userid = form.get("userid", None)
        password1 = form.get("password1", None)
        password2 = form.get("password2", None)
        messages = IStatusMessage(self.request)
        registration = getToolByName(self.context, 'portal_registration')

        if userid is None:
            messages.add(_('No user has been specified'), "error")
        elif password1 is password2 is None:
            return self.index()
        else:
            mt = getToolByName(self.context, "portal_membership")
            member = mt.getMemberById(userid)
            if member is None:
                messages.add(_('Invalid user id'), "error")
            else:
                fail_message = registration.testPasswordValidity(
                    password1, password2)
                if fail_message:
                    messages.add(pmf(fail_message), "error")
                else:
                    member.setSecurityProfile(password=password1)
                    messages.add(pmf("Password changed"), "info")
        return self.index()
コード例 #3
0
class SGMSettingsEditForm(controlpanel.RegistryEditForm):
    """Media settings form.
    """
    schema = ISimpleGroupManagementSettings
    id = "SGMSettingsEditForm"
    label = _("Groups management proxy settings")
    description = _(
        "help_sgm_settings_editform",
        default="Configure groups management proxy"  # noqa
    )

    @button.buttonAndHandler(pmf('Save'), name='save')
    def handleSave(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return
        changes = self.applyChanges(data)
        IStatusMessage(self.request).addStatusMessage(_("Changes saved"),
                                                      "info")
        self.context.REQUEST.RESPONSE.redirect(
            "@@configure-simple-groups-management"
        )

    @button.buttonAndHandler(pmf('Cancel'), name='cancel')
    def handleCancel(self, action):
        IStatusMessage(self.request).addStatusMessage(_("Edit cancelled"),
                                                      "info")
        self.request.response.redirect("%s/%s" % (self.context.absolute_url(),
                                                  self.control_panel_view))

    def updateWidgets(self):
        super(SGMSettingsEditForm, self).updateWidgets()
        fix_widget_style(self.widgets['sgm_data'])
        fix_widget_style(self.widgets['sgm_never_managed_groups'])
コード例 #4
0
class IMediaViewTile(IPersistentCoverTile):
    title = schema.TextLine(
        title=pmf(u'Title'),
        required=False
    )

    description = schema.Text(
        title=pmf(u'Description'),
        required=False
    )

    uuid = schema.TextLine(
        title=pmf(u'UUID'),
        required=False,
        readonly=True
    )
コード例 #5
0
    def __call__(self):
        objs = self._lookup_objects_by_path(self.request.form.get('paths', []))

        # Redirects to the original template if the user aborted the confirmation.
        if 'form.button.Cancel' in self.request.form:
            return self._redirect_to_orig_template()

        # Check if one or more objects are selected
        if not objs:
            api.portal.show_message(
                pmf(u'Please select one or more items to delete.'),
                self.request,
                type="error")
            return self._redirect_to_orig_template()

        # Split the given objects into objects with backrefs and objects without backrefs
        self.objs_without_backrefs, self.objs_with_backrefs = self._check_backreferences_for_objs(
            objs)

        # Delete the given objects
        if 'form.submitted' in self.request.form:
            try:
                return self._handle_form_submitted(self.request)
            except Forbidden:
                return self._redirect_to_orig_template()

        # Returns a confirmation-template
        return super(FolderDeleteConfirmation, self).__call__()
コード例 #6
0
class IAnalyticsSettings(Interface):
    """Settings used in the control panel for analyticspanel: general panel
    """

    general_code = schema.Text(
        title=pmf(u"JavaScript for web statistics support"),
        description=pmf(
            u"For enabling web statistics support from external providers (for e.g. Google Analytics). "
            u"Paste the code snippets provided. It will be included in the rendered HTML as entered near the end of the page."
        ),
        default=u"",
        missing_value=u"",
        required=False,
    )

    error_specific_code = schema.Tuple(
        title=_(u'JavaScript to be included when an error message is get'),
        description=_(
            'help_error_specific_code',
            default=
            u"Replace default code included when an error message returned is "
            "one of the following values.\n"
            "For example: use \"NotFound\" for change JavaScript included inside NotFound page."
        ),
        value_type=PersistentObject(IErrorCodeValuePair,
                                    title=_(u"Error message related snippet")),
        required=False,
        default=(),
        missing_value=(),
    )

    path_specific_code = schema.Tuple(
        title=_(u"JavaScript to be included inside specific site's paths"),
        description=_(
            'help_path_specific_code',
            default=
            u'Put there an absolute site path, and the statistics code you want to use '
            u'there instead of the default ones.\n'
            u'The most specific path will be used.\n'
            u'Example: /folder/subfolder'),
        value_type=PersistentObject(ISitePathValuePair,
                                    title=_(u"Site path related snippet")),
        required=False,
        default=(),
        missing_value=(),
    )
コード例 #7
0
ファイル: hwtools.py プロジェクト: syslabcom/osha.hw2010
 def len_month(self, date):
     """ fetches a monthname and returns translation plus lenght """
     if type(date)== StringType:
         date = DateTime(date)
     month = date.aMonth().lower()
     label = 'month_'+month
     tmonth = pmf(label)
     return (tmonth, len(tmonth))
     
コード例 #8
0
ファイル: views.py プロジェクト: jean/wildcard.media
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        self.applyChanges(data)

        self.status = pmf("Changes saved.")
コード例 #9
0
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        self.applyChanges(data)

        self.status = pmf('Changes saved.')
コード例 #10
0
 def handleApply(self, action):
     data, errors = self.extractData()
     if errors:
         self.status = self.formErrorsMessage
         return
     self.applyChanges(data)
     IStatusMessage(self.request).addStatusMessage(
         pmf(u"Changes saved"),
     )
     self.request.response.redirect(self.context.absolute_url())
コード例 #11
0
def get_proposal_transitions_vocabulary(context):
    """Vocabulary with all proposal transitions valid for current state."""

    wftool = api.portal.get_tool('portal_workflow')
    transitions = []
    for tdef in wftool.getTransitionsFor(context):
        transitions.append(
            SimpleVocabulary.createTerm(
                tdef['id'], tdef['id'],
                pmf(tdef['id'], default=tdef['title_or_id'])))
    return SimpleVocabulary(transitions)
コード例 #12
0
ファイル: views.py プロジェクト: kroman0/products
    def __call__( self ):
        """ Perform the update and redirect if necessary, or render the page.
        """
        context = aq_inner(self.context)
        request = self.request

        content_types_seoprops_enabled = request.get( 'contentTypes', [] )
        exposeDCMetaTags = request.get( 'exposeDCMetaTags', None )
        additionalKeywords = request.get('additionalKeywords', [])
        default_custom_metatags = request.get('default_custom_metatags', [])
        metatags_order = request.get('metatags_order', [])
        filterKeywordsByContent = request.get('filterKeywordsByContent', None)
        settingsUseKeywordsSG = int(request.get('settingsUseKeywordsSG', 1))
        settingsUseKeywordsLG = int(request.get('settingsUseKeywordsLG', 1))

        site_props = getToolByName(self.portal_properties, 'site_properties')
        seo_props = getToolByName(self.portal_properties, 'seo_properties')

        form = self.request.form
        submitted = form.get('form.submitted', False)

        if submitted:
            site_props.manage_changeProperties(exposeDCMetaTags=exposeDCMetaTags)
            seo_props.manage_changeProperties(additional_keywords=additionalKeywords)
            seo_props.manage_changeProperties(default_custom_metatags=default_custom_metatags)
            seo_props.manage_changeProperties(metatags_order=metatags_order)
            seo_props.manage_changeProperties(content_types_seoprops_enabled=content_types_seoprops_enabled)
            seo_props.manage_changeProperties(filter_keywords_by_content=filterKeywordsByContent)
            seo_props.manage_changeProperties(settings_use_keywords_sg=settingsUseKeywordsSG)
            seo_props.manage_changeProperties(settings_use_keywords_lg=settingsUseKeywordsLG)

            for ptype in self.portal_types.objectValues():
                acts = filter(lambda x: x.id == 'seo_properties', ptype.listActions())
                action = acts and acts[0] or None
                if ptype.getId() in content_types_seoprops_enabled:
                    if action is None:
                        ptype.addAction('seo_properties',
                                        'SEO Properties',
                                        'string:${object_url}/@@seo-context-properties',
                                        "python:exists('portal/@@seo-context-properties')",
                                        'Modify portal content',
                                        'object',
                                        visible=1)
                else:
                    if action !=None:
                        actions = list(ptype.listActions())
                        ptype.deleteActions([actions.index(a) for a in actions if a.getId()=='seo_properties'])
            context.plone_utils.addPortalMessage(pmf(u'Changes saved.'))
            return request.response.redirect('%s/%s'%(self.context.absolute_url(), 'plone_control_panel'))
        else:
            return self.template(contentTypes=content_types_seoprops_enabled, exposeDCMetaTags=exposeDCMetaTags)
コード例 #13
0
class ServiceNavigationForm(AutoExtensibleForm, EditForm):
    template = ViewPageTemplateFile('templates/form.pt')

    schema = IServiceNavigationSchema
    ignoreContext = False
    name = "service-edit-form"

    label = _(u'label_service_navigation', default=u'Service navigation')

    @button.buttonAndHandler(pmf(u'Save'), name='save')
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return
        self.applyChanges(data)
        IStatusMessage(self.request).addStatusMessage(
            pmf(u"Changes saved"),
        )
        self.request.response.redirect(self.context.absolute_url())

    @button.buttonAndHandler(pmf(u'Cancel'), name='cancel')
    def handleCancel(self, action):
        IStatusMessage(self.request).addStatusMessage(
            pmf(u"Edit cancelled"),
        )
        self.request.response.redirect(self.context.absolute_url())

    def updateActions(self):
        super(EditForm, self).updateActions()
        self.actions["save"].addClass("context")
        self.actions["cancel"].addClass("standalone")

    def getContent(self):
        annotations = IAnnotations(self.context)
        if ANNOTATION_KEY not in annotations:
            annotations[ANNOTATION_KEY] = PersistentMapping()
        return ServiceNavigationConfig(annotations[ANNOTATION_KEY])
コード例 #14
0
 def title(self):
     itemsToAdd = self._itemsToAdd()
     showConstrainOptions = self._showConstrainOptions()
     custom_menu_results = self.getCustomMenuResults()
     if custom_menu_results:
         if not showConstrainOptions and len(itemsToAdd) == 1:
             title = custom_menu_results.get('title')
             title = translate(_safe_unicode(title),
                               domain='plone',
                               context=self.request)
             return pmf(u'label_add_type',
                        default='Add ${type}',
                        mapping={'type': title})
     title = super(FactoriesSubMenuItem, self).title
     return title
コード例 #15
0
class GlobalSettingsForm(group.GroupForm, form.EditForm):
    groups = (DefaultGroup, ConversionSettingsGroup)

    label = _(u"Media Settings")
    description = _(u'description_media_global_settings_form',
                    default=u"Configure the parameters for media.")

    @button.buttonAndHandler(pmf('Save'), name='apply')
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        self.applyChanges(data)

        self.status = pmf('Changes saved.')
コード例 #16
0
 def handleSubmit(self, action):
     data, errors = self.extractData()
     if errors:
         self.status = self.formErrorsMessage
         return
     registrants = data.get("registrants", [])
     waiting_list = data.get("waiting_list", [])
     if not registrants and not waiting_list:
         api.portal.show_message(
             message=_(
                 "contact_recipients_error",
                 default=u"You need to select at least one recipient from"
                 u" registrants or waiting_list list.",
             ),
             request=self.request,
             type="error",
         )
         return
     email_addresses = self.extract_recipients(registrants, waiting_list)
     if isinstance(email_addresses, str):
         api.portal.show_message(message=email_addresses,
                                 request=self.request,
                                 type="error")
         return
     try:
         self.send_message(data=data, email_addresses=email_addresses)
         api.portal.show_message(
             message=_("contact_recipients_sent", u"Emails sent."),
             request=self.request,
         )
         self.request.response.redirect(self.nextURL())
     except (SMTPException, RuntimeError) as e:
         logger.exception(e)
         plone_utils = api.portal.get_tool(name="plone_utils")
         exception = plone_utils.exceptionString()
         message = pmf(
             u"Unable to send mail: ${exception}",
             mapping={u"exception": exception},
         )
         api.portal.show_message(message=message,
                                 request=self.request,
                                 type="error")
コード例 #17
0
 def title(self):
     itemsToAdd = self._itemsToAdd()
     showConstrainOptions = self._showConstrainOptions()
     custom_menu_results = self.getCustomMenuResults()
     if custom_menu_results:
         if not showConstrainOptions and len(itemsToAdd) == 1:
             title = custom_menu_results.get('title')
             title = translate(_safe_unicode(title),
                               domain='plone',
                               context=self.request)
             return pmf(u'label_add_type', default='Add ${type}',
                        mapping={'type' : title})
     #title = super(FactoriesSubMenuItem, self).title
     try:
         # Plone 3: it's a @property
         title = PloneFactoriesSubMenuItem.title.fget(self)
     except AttributeError:
         # Plone 4, it's only a zope.i18nmessageid.message.Message
         title = super(FactoriesSubMenuItem, self).title
     return title
コード例 #18
0
    def __call__(self):
        objs = self._lookup_objects_by_path(self.request.form.get('paths', []))

        # Redirects to the original template if the user aborted the confirmation.
        if 'form.button.Cancel' in self.request.form:
            return self._redirect_to_orig_template()

        # Check if one or more objects are selected
        if not objs:
            api.portal.show_message(pmf(u'Please select one or more items to delete.'), self.request, type="error")
            return self._redirect_to_orig_template()

        # Split the given objects into objects with backrefs and objects without backrefs
        self.objs_without_backrefs, self.objs_with_backrefs = self._check_backreferences_for_objs(objs)

        # Delete the given objects
        if 'form.submitted' in self.request.form:
            try:
                return self._handle_form_submitted(self.request)
            except Forbidden:
                return self._redirect_to_orig_template()

        # Returns a confirmation-template
        return super(FolderDeleteConfirmation, self).__call__()
コード例 #19
0
    def __call__(self):
        registry = getUtility(IRegistry)
        TWITTER_CONSUMER_KEY = registry.get('cs.auth.twitter.controlpanel.ITwitterLoginSettings.twitter_consumer_key').encode()
        TWITTER_CONSUMER_SECRET = registry.get('cs.auth.twitter.controlpanel.ITwitterLoginSettings.twitter_consumer_secret').encode()

        oauth_token = self.request.get('oauth_token')
        oauth_verifier = self.request.get('oauth_verifier')

        sdm = getToolByName(self.context, "session_data_manager")
        session = sdm.getSessionData(create=False)

        # Check if the provided oauth_token and the one we have from the
        # previous step are the same.
        if oauth_token != session[AuthorizationTokenKeys.oauth_token]:
            msg = _(u"Your oauth token is not correct. Please try again")
            IStatusMessage(self.request).add(msg, type="error")
            self.request.response.redirect(self.context.absolute_url())
            return u""

        # Check if the provided verifier is OK, querying Twitter API.
        token = oauth.Token(
            session[AuthorizationTokenKeys.oauth_token],
            session[AuthorizationTokenKeys.oauth_token_secret],
        )
        consumer = oauth.Consumer(
            key=TWITTER_CONSUMER_KEY,
            secret=TWITTER_CONSUMER_SECRET
        )
        client = oauth.Client(consumer, token)
        args = {
            'oauth_verifier': oauth_verifier,
        }
        body = urllib.urlencode(args)
        resp, content = client.request(TWITTER_ACCESS_TOKEN_URL, 'POST', body)
        if resp.get('status', '999') != '200':
            msg = _(u"Error authenticating with Twitter. Please try again.")
            IStatusMessage(self.request).add(msg, type="error")
            self.request.response.redirect(self.context.absolute_url())
            return u""

        # Save the data in the session so that the extraction plugin can
        # authenticate the user to Plone and save the oauth_token
        # for future queries to Twitter API
        access_token = dict(parse_qsl(content))
        session = sdm.getSessionData(create=False)
        session[SessionKeys.user_id] = str(access_token['user_id'])
        session[SessionKeys.screen_name] = access_token['screen_name']
        session[SessionKeys.oauth_token] = access_token['oauth_token']
        session[SessionKeys.oauth_token_secret] = access_token['oauth_token_secret']

        # Query Twitter API for user data
        token = oauth.Token(
            session[SessionKeys.oauth_token],
            session[SessionKeys.oauth_token_secret],
        )
        consumer = oauth.Consumer(
            key=TWITTER_CONSUMER_KEY,
            secret=TWITTER_CONSUMER_SECRET
        )
        client = oauth.Client(consumer, token)
        args = {
            'user_id': session[SessionKeys.user_id]
        }
        body = urllib.urlencode(args)
        url = TWITTER_USER_DATA_URL + '?' + body
        resp, content = client.request(url, 'GET')
        if resp.get('status', '999') != '200':
            msg = _(u"Error getting user information. Please try again.")
            IStatusMessage(self.request).add(msg, type="error")
            self.request.response.redirect(self.context.absolute_url())
            return u""

        us = json.loads(content)
        session[SessionKeys.screen_name] = us.get(u'screen_name', '')
        session[SessionKeys.name] = us.get(u'name', session[SessionKeys.screen_name])
        session[SessionKeys.profile_image_url] = us.get(u'profile_image_url', '')
        session[SessionKeys.description] = us.get(u'description', '')
        session[SessionKeys.location] = us.get(u'location')
        session.save()

        # Add user data into our plugin storage:
        acl = self.context.acl_users
        acl_plugins = acl.plugins
        ids = acl_plugins.listPluginIds(IExtractionPlugin)
        for id in ids:
            plugin = getattr(acl_plugins, id)
            if ICSTwitterPlugin.providedBy(plugin):
                if plugin._storage.get(session[SessionKeys.user_id], None) is None:
                    user_data = {
                        'screen_name': session[SessionKeys.screen_name],
                        'fullname': session[SessionKeys.name],
                        'profile_image_url': session[SessionKeys.profile_image_url],
                        'description': session[SessionKeys.description],
                        'location': session[SessionKeys.location]
                    }
                    plugin._storage[session[SessionKeys.user_id]] = user_data

        msg = pmf(u"Welcome. You are now logged in.")
        IStatusMessage(self.request).add(msg, type="info")

        return_args = ''
        if self.request.get('came_from', None) is not None:
            return_args = {'came_from': self.request.get('came_from')}
            return_args = '?' + urllib.urlencode(return_args)

        return_url = self.context.absolute_url() + '/logged_in' + return_args
        self.request.response.redirect(return_url)
コード例 #20
0
ファイル: view.py プロジェクト: Vinsurya/Plone
    def _save(self):
        """Save a new row or update one"""
        form = self.request.form
        context = self.context
        storage = self.storage
        configuration = self.configuration
        row_index = form.get('row-index', -1)
        tp_catalog = getToolByName(context, config.CATALOG_ID)
        if context.getInsertType()=='prepend':
            # this is the first row in the section, so you want to add something above it
            row_index = self._first_index_in_section(row_index)
        else:
            # this is the last row in the section, so you want to add something below it (default)
            row_index = self._last_index_in_section(row_index)
        # Run validations
        for conf in configuration:
            id = conf['id']
            col_type = conf['type']
            field = getMultiAdapter((context, self.request),
                                    IColumnField, name=col_type)

            validators = getAdapters((field, ),
                                     IFieldValidator)
            for name, validator in validators:
                msg = validator.validate(conf)
                if msg:
                    self.errors[id] = msg
                    break

        to_be_saved = {}
        if not self.errors:
            # As some IColumnDataRetriever adapter do some stuff, we read data only if no error has been get
            for conf in configuration:
                id = conf['id']
                col_type = conf['type']
                try:
                    retriever = getAdapter(context,
                                           IColumnDataRetriever,
                                           name=col_type)
                except ComponentLookupError:
                    retriever = IColumnDataRetriever(context)
                try:
                    data = retriever.get_from_request(id, form)
                except NotImplementedError:
                    data = None
                if data:
                    to_be_saved.update(**data)
        else:
            putils = getToolByName(context, 'plone_utils')
            putils.addPortalMessage(pmf(u'Please correct the indicated errors.'), type="error")
            return
        
        if to_be_saved:
            member = getMultiAdapter((context, self.request), name=u'plone_portal_state').member()
            _ = getToolByName(context, 'translation_service').utranslate
            if form.get('row-index') is not None and not form.get('addRow'):
                # Edit row
                row_index = form.get('row-index')
                if not self.check_manager_or_mine_record(row_index):
                    raise Unauthorized("You can't modify that record")
                to_be_saved['__uuid__'] = storage[row_index]['__uuid__']
                storage.update(row_index, to_be_saved)
                self._addNewVersion(_(msgid="Row changed",
                                      domain="collective.tablepage",
                                      context=context))
            else:
                # Add row
                to_be_saved['__creator__'] = member.getId()
                to_be_saved['__uuid__'] = str(uuid.uuid4())
                storage.add(to_be_saved, row_index)
                self._addNewVersion(_(msgid="Row added",
                                      domain="collective.tablepage",
                                      context=context))
            self._populateCache(storage, row_index)
            tp_catalog.catalog_row(context, storage[row_index])
コード例 #21
0
ファイル: view.py プロジェクト: tuxwerk/collective.tablepage
    def _save(self):
        """Save a new row or update one"""
        form = self.request.form
        context = self.context
        storage = self.storage
        configuration = self.configuration
        row_index = form.get('row-index', -1)
        tp_catalog = getToolByName(context, config.CATALOG_ID)
        if context.getInsertType() == 'prepend':
            # this is the first row in the section, so you want to add something above it
            row_index = self._first_index_in_section(row_index)
        else:
            # this is the last row in the section, so you want to add something below it (default)
            row_index = self._last_index_in_section(row_index)
        # Run validations
        for conf in configuration:
            id = conf['id']
            col_type = conf['type']
            field = getMultiAdapter((context, self.request),
                                    IColumnField,
                                    name=col_type)

            validators = getAdapters((field, ), IFieldValidator)
            for name, validator in validators:
                msg = validator.validate(conf)
                if msg:
                    self.errors[id] = msg
                    break

        to_be_saved = {}
        if not self.errors:
            # As some IColumnDataRetriever adapter do some stuff, we read data only if no error has been get
            for conf in configuration:
                id = conf['id']
                col_type = conf['type']
                try:
                    retriever = getAdapter(context,
                                           IColumnDataRetriever,
                                           name=col_type)
                except ComponentLookupError:
                    retriever = IColumnDataRetriever(context)
                try:
                    data = retriever.get_from_request(id, form)
                except NotImplementedError:
                    data = None
                if data:
                    to_be_saved.update(**data)
        else:
            putils = getToolByName(context, 'plone_utils')
            putils.addPortalMessage(
                pmf(u'Please correct the indicated errors.'), type="error")
            return
        if to_be_saved:
            member = getMultiAdapter((context, self.request),
                                     name=u'plone_portal_state').member()
            _ = getToolByName(context, 'translation_service').utranslate
            to_be_saved['__tablerowstyle__'] = form.get('__tablerowstyle__')
            if form.get('row-index') is not None and not form.get('addRow'):
                # Edit row
                row_index = form.get('row-index')
                if not self.check_manager_or_mine_record(row_index):
                    raise Unauthorized("You can't modify that record")
                to_be_saved['__uuid__'] = storage[row_index]['__uuid__']
                storage.update(row_index, to_be_saved)
                self._addNewVersion(
                    _(msgid="Row changed",
                      domain="collective.tablepage",
                      context=context))
            else:
                # Add row
                to_be_saved['__creator__'] = member.getId()
                to_be_saved['__uuid__'] = str(uuid.uuid4())
                storage.add(to_be_saved, row_index)
                self._addNewVersion(
                    _(msgid="Row added",
                      domain="collective.tablepage",
                      context=context))
            self._populateCache(storage, row_index)
            tp_catalog.catalog_row(context, storage[row_index])
コード例 #22
0
ファイル: helper.py プロジェクト: pemzurigo/opengever.core
def _linked_document_with_tooltip(item, value, trashed=False):

    data = {}

    if isinstance(value, unicode):
        value = value.encode('utf-8')
    data['value'] = value

    # Determine URL method
    data['url'] = '#'
    if hasattr(item, 'getURL'):
        data['url'] = item.getURL()
    elif hasattr(item, 'absolute_url'):
        data['url'] = item.absolute_url()

    # tooltip links
    data['preview_link'] = '%s/@@download_pdfpreview' % (data['url'])
    data['preview_label'] = translate(
        base_mf(u'button_pdf', 'PDF'), context=item.REQUEST).encode('utf-8')

    data['edit_metadata_link'] = '%s/edit_checker' % (data['url'])
    data['edit_metadata_label'] = translate(
        pmf(u'Edit metadata'), context=item.REQUEST).encode('utf-8')

    data['edit_direct_link'] = '%s/editing_document' % (data['url'])
    data['edit_direct_label'] = translate(
        pmf(u'Checkout and edit'), context=item.REQUEST).encode('utf-8')

    # Construct CSS class
    data['css_class'] = get_css_class(item)

    # Construct breadcrumbs
    breadcrumb_titles = _breadcrumbs_from_item(item)
    data['breadcrumbs'] = " > ".join(t for t in breadcrumb_titles)

    # Make sure all data used in the HTML snippet is properly escaped
    for k, v in data.items():
        data[k] = cgi.escape(v, quote=True)

    tooltip_links = []

    is_doc = item.portal_type == 'opengever.document.document'

    if is_doc and PDFCONVERTER_AVAILABLE:
        tooltip_links.append("""<a href='%(preview_link)s'>
                    %(preview_label)s
                </a>""" % data)

    if not trashed:
        tooltip_links.append("""<a href='%(edit_metadata_link)s'>
                    %(edit_metadata_label)s
                </a>""" % data)

    if is_doc and not trashed:
        tooltip_links.append("""<a href='%(edit_direct_link)s'>
                    %(edit_direct_label)s
                </a>""" % data)

    data['tooltip_links'] = """
                """.join(tooltip_links)

    link = """<div class='linkWrapper'>
    <a class='tabbedview-tooltip %(css_class)s' href='%(url)s'></a>
    <a href='%(url)s'>%(value)s</a>
    <div class='tabbedview-tooltip-data'>
        <div class='tooltip-content'>
            <div class='tooltip-header'>%(value)s</div>
            <div class='tooltip-breadcrumb'>%(breadcrumbs)s</div>
            <div class='tooltip-links'>
                %(tooltip_links)s
            </div>
        </div>
        <div class='bottomImage'></div>
    </div>
</div>""" % data

    return link
コード例 #23
0
ファイル: response.py プロジェクト: lukasgraf/opengever.core
 def label(self):
     return translate(
         pmf('label_add_comment', default='Add Comment'),
         context=self.request)
コード例 #24
0
    results = catalog(**params)
except ParseError:
    results = []
    has_parse_errors = True

searchterm_query = '?searchterm=%s' % url_quote_plus(q)

REQUEST = context.REQUEST
RESPONSE = REQUEST.RESPONSE
RESPONSE.setHeader('Content-Type', 'text/xml;charset=%s' % site_encoding)

# replace named entities with their numbered counterparts, in the xml the named ones are not correct
#   &darr;      --> &#8595;
#   &hellip;    --> &#8230;
legend_livesearch = pmf(
    'legend_livesearch',
    default='LiveSearch &#8595;')
label_no_results_found = pmf(
    'label_no_results_found',
    default='No matching results found.')
label_has_parse_errors = pmf(
    'label_has_parse_errors',
    default='There were errors parsing your query, please note that boolean '
            'expressions like AND, NOT and OR are only allowed in advanced '
            'search.')
label_advanced_search = pmf(
    'label_advanced_search',
    default='Advanced Search&#8230;')
label_show_all = pmf(
    'label_show_all',
    default='Show all items')
コード例 #25
0
 def handleCancel(self, action):
     IStatusMessage(self.request).addStatusMessage(
         pmf(u"Edit cancelled"),
     )
     self.request.response.redirect(self.context.absolute_url())
コード例 #26
0
## Script (Python) "mail_password"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##title=Mail a user's password
##parameters=

from Products.CMFPlone import PloneMessageFactory as pmf
from Products.remember.pas.utils import getUserIdForEmail
from Products.remember.pas.utils import email_login_is_active

REQUEST = context.REQUEST
userid = REQUEST['userid']
if '@' in userid and email_login_is_active():
    userid = getUserIdForEmail(context, userid) or userid
try:
    response = context.portal_registration.mailPassword(userid, REQUEST)
except ValueError, e:
    context.plone_utils.addPortalMessage(pmf(str(e)))
    response = context.mail_password_form()
return response
コード例 #27
0
 def label(self):
     return pmf('tabs_home', default="Home")
コード例 #28
0
    def __call__(self):
        registry = getUtility(IRegistry)
        GOOGLEPLUS_CLIENT_ID = registry.get('cs.auth.googleplus.controlpanel.IGooglePlusLoginSettings.googleplus_client_id').encode()
        GOOGLEPLUS_CLIENT_SECRET = registry.get('cs.auth.googleplus.controlpanel.IGooglePlusLoginSettings.googleplus_client_secret').encode()

        verificationCode = self.request.form.get("code", None)
        error = self.request.form.get("error", None)
        errorReason = self.request.form.get("error_reason", None)

        salt = hashlib.sha256().hexdigest()
        session = ISession(self.request)
        session[GOOGLEPLUS_AUTHENTICATION_SALT_KEY] = salt
        args = {
                'state': STATE,
                'scope': PERMISSIONS,
                'client_id': GOOGLEPLUS_CLIENT_ID,
                'redirect_uri': "%s/%s" % (self.context.absolute_url(),
                                           self.__name__),
                'response_type': RESPONSE,
            }

        # Did we get an error back after a Google+ redirect?
        if error is not None or errorReason is not None:
            log.info(error)
            log.info(errorReason)
            IStatusMessage(self.request).add(_(
                u"GOOGLEPLUS authentication denied"), type="error")
            self.request.response.redirect(self.context.absolute_url())
            return u""

        # Check if this the status is the same...
        return_salt = self.request.form.get('status', '')
        session_salt = session.get(GOOGLEPLUS_AUTHENTICATION_SALT_KEY)
        if return_salt and return_salt != session_salt:
            IStatusMessage(self.request).add(_(
                u"GooglePlus authentication denied"), type="error")
            self.request.response.redirect(self.context.absolute_url())
            log.info('%s != %s' % (
                return_salt,
                session.get(GOOGLEPLUS_AUTHENTICATION_SALT_KEY)))
            return u""

        # If there is no code, this is probably the first request, so redirect
        # to Google+
        if verificationCode is None:
            self.request.response.redirect(
                    "%s?%s" % (GOOGLEPLUS_AUTH_URL, urllib.urlencode(args),)
                )
            return u""

        # If we are on the return path form Google+,
        # exchange the return code for a token
        args = {
            'code': verificationCode,
            'client_id': GOOGLEPLUS_CLIENT_ID,
            'client_secret': GOOGLEPLUS_CLIENT_SECRET,
            'redirect_uri': "%s/%s" % (
                self.context.absolute_url(),
                self.__name__),
            'grant_type': GRANT,
            }

        response = requests.post(GOOGLEPLUS_ACCESS_TOKEN_URL, data=args)

        #Load the profile using the access token we just received
        accessToken = response.json()["access_token"]

        def unicode_to_utf8(data):
            if isinstance(data, unicode):
                return data.encode('utf-8')
            else:
                return data

        def dict_unicode_to_utf8(data):
            new_data = {}
            for key, value in data.items():
                new_data[unicode_to_utf8(key)] = unicode_to_utf8(value)
            return new_data

        profile = json.load(urllib.urlopen(
                "%s?%s" % (
                    GOOGLEPLUS_PROFILE_URL,
                    urllib.urlencode({'access_token': accessToken}),)
            ), object_hook=dict_unicode_to_utf8)

        userId = profile.get('id')
        name = profile.get('name')
        email = profile.get('email', '')
        username = profile.get('name')
        profile_image = profile.get('picture')

        if not userId:
            IStatusMessage(self.request).add(
                _(u"Insufficient information in GooglePlus profile"),
                type="error")
            self.request.response.redirect(self.context.absolute_url())
            return

        # Save the data in the session so that the extraction plugin can
        # authenticate the user to Plone
        session[SessionKeys.accessToken] = accessToken
        session[SessionKeys.userId] = userId
        session[SessionKeys.userName] = username
        session[SessionKeys.fullname] = name
        session[SessionKeys.email] = email
        session[SessionKeys.profile_image] = profile_image
        session.save()

        # Add user data into our plugin storage:
        acl = self.context.acl_users
        initial_login = acl.getUserById(userId) is None

        acl_plugins = acl.plugins
        ids = acl_plugins.listPluginIds(IExtractionPlugin)
        for id in ids:
            plugin = getattr(acl_plugins, id)
            if ICSGooglePlusPlugin.providedBy(plugin):
                user_data = plugin._storage.get(
                    session[SessionKeys.userId], {})
                user_data['username'] = session[SessionKeys.userName]
                user_data['fullname'] = session[SessionKeys.fullname]
                user_data['email'] = session[SessionKeys.email]
                plugin._storage[session[SessionKeys.userId]] = user_data

        IStatusMessage(self.request).add(
            pmf(u"Welcome! You are now logged in."),
            type="info")

        return_args = ''
        if self.request.get('came_from', None) is not None:
            return_args = {'came_from': self.request.get('came_from')}
            return_args = '?' + urllib.urlencode(return_args)

        user = acl.getUserById(userId)
        if initial_login:
            notify(GoogleUserRegisteredEvent(user, profile))
        else:
            notify(GoogleUserLoggedInEvent(user, profile))

        self.request.response.redirect(
            self.context.absolute_url() + '/logged_in' + return_args)
コード例 #29
0
## Script (Python) "mail_password"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##title=Mail a user's password
##parameters=

from Products.CMFPlone import PloneMessageFactory as pmf
from AccessControl import Unauthorized
REQUEST=context.REQUEST
try:
    response = context.portal_registration.mailPassword(REQUEST['userid'], REQUEST)
except ValueError, e:
    try:
        msg = pmf(e.message)
    except Unauthorized:
        try:
            msg = pmf(str(e))
        except Unauthorized:
            # If we are not allowed to tell the user, what is wrong, he
            # should get an error message and contact the admins
            raise e
    context.plone_utils.addPortalMessage(msg)
    response = context.mail_password_form()
return response
コード例 #30
0
else:
    params['path'] = path

# search limit+1 results to know if limit is exceeded
results = catalog(REQUEST, **params)

searchterm_query = '?searchterm=%s' % url_quote_plus(q)

RESPONSE = REQUEST.RESPONSE
RESPONSE.setHeader('Content-Type', 'text/xml;charset=utf-8')

# replace named entities with their numbered counterparts, in the xml the named
# ones are not correct
#   &darr;      --> &#8595;
#   &hellip;    --> &#8230;
legend_livesearch = pmf('legend_livesearch', default='LiveSearch &#8595;')
label_no_results_found = pmf('label_no_results_found',
                             default='No matching results found.')
label_advanced_search = pmf('label_advanced_search',
                            default='Advanced Search&#8230;')
label_show_all = pmf('label_show_all', default='Show all items')

ts = getToolByName(context, 'translation_service')

output = []


def write(s):
    output.append(safe_unicode(s))

コード例 #31
0
 def label(self):
     return translate(pmf('label_add_comment', default='Add Comment'),
                      context=self.request)
コード例 #32
0
ファイル: course.py プロジェクト: albertduran/video.converter
 def no_items_message(self):
     return pmf(
         'description_no_videos_in_folder',
         default=u'There are currently no videos in this folder.'
     )
コード例 #33
0
## Script (Python) "mail_password"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##title=Mail a user's password
##parameters=

from Products.CMFPlone import PloneMessageFactory as pmf
from AccessControl import Unauthorized

REQUEST = context.REQUEST
try:
    response = context.portal_registration.mailPassword(
        REQUEST.get('userid', ''), REQUEST)
except ValueError as e:
    try:
        msg = pmf(str(e))
    except Unauthorized:
        # If we are not allowed to tell the user, what is wrong, he
        # should get an error message and contact the admins
        raise e
    context.plone_utils.addPortalMessage(msg)
    response = context.mail_password_form()
return response
コード例 #34
0
 def _handle_form_submitted(self, REQUEST=None):
     api.portal.show_message(pmf(u'Items successfully deleted.'),
                             self.request,
                             type="info")
     self._delete_objs(self.objs_without_backrefs)
     return self._redirect_to_orig_template()
コード例 #35
0
## Script (Python) "mail_password"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##title=Mail a user's password
##parameters=

from Products.CMFPlone import PloneMessageFactory as pmf
from Products.remember.pas.utils import getUserIdForEmail
from Products.remember.pas.utils import email_login_is_active

REQUEST=context.REQUEST
userid = REQUEST['userid']
if '@' in userid and email_login_is_active():
    userid = getUserIdForEmail(context, userid) or userid
try:
    response = context.portal_registration.mailPassword(userid, REQUEST)
except ValueError, e:
    context.plone_utils.addPortalMessage(pmf(str(e)))
    response = context.mail_password_form()
return response
コード例 #36
0
 def __call__(self, context):
     return SimpleVocabulary([
         SimpleTerm('dmsincomingmail', title=pmf(u'Incoming Mail')),
         SimpleTerm('dmsincoming_email', title=pmf(u'Incoming Email'))
     ])
コード例 #37
0
ファイル: course.py プロジェクト: albertduran/video.converter
 def no_subjects_message(self):
     return pmf(
         'description_no_subjects_configured',
         default=u'There are currently no subjects configured to show videos\
                   or videos in this folder are not categorized.'
     )
コード例 #38
0
## Script (Python) "mail_password"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##title=Mail a user's password
##parameters=

from Products.CMFPlone import PloneMessageFactory as pmf
from AccessControl import Unauthorized

REQUEST = context.REQUEST
try:
    response = context.portal_registration.mailPassword(
                    REQUEST.get('userid'), REQUEST)
except ValueError, e:
    try:
        msg = pmf(str(e))
    except Unauthorized:
        # If we are not allowed to tell the user, what is wrong, he
        # should get an error message and contact the admins
        raise e
    context.plone_utils.addPortalMessage(msg)
    response = context.mail_password_form()
return response
コード例 #39
0
try:
    results = catalog(**params)
except ParseError:
    results = []
    has_parse_errors = True

searchterm_query = '?searchterm=%s' % url_quote_plus(q)

REQUEST = context.REQUEST
RESPONSE = REQUEST.RESPONSE
RESPONSE.setHeader('Content-Type', 'text/xml;charset=%s' % site_encoding)

# replace named entities with their numbered counterparts, in the xml the named ones are not correct
#   &darr;      --> &#8595;
#   &hellip;    --> &#8230;
legend_livesearch = pmf('legend_livesearch', default='LiveSearch &#8595;')
label_no_results_found = pmf('label_no_results_found',
                             default='No matching results found.')
label_has_parse_errors = pmf(
    'label_has_parse_errors',
    default='There were errors parsing your query, please note that boolean '
    'expressions like AND, NOT and OR are only allowed in advanced '
    'search.')
label_advanced_search = pmf('label_advanced_search',
                            default='Advanced Search&#8230;')
label_show_all = pmf('label_show_all', default='Show all items')

ts = getToolByName(context, 'translation_service')

output = []
コード例 #40
0
class Content(DataPlugin):
    implements(IDataPlugin)

    name = 'content'
    title = _(u'Content Metadata')
    description = _(u'''Content information''')

    portal_types = [
        pmf(u'Document'),
        pmf(u'Event'),
        pmf(u'File'),
        pmf(u'Folder'),
        pmf(u'Image'),
        pmf(u'News Item')
    ]

    def __init__(self, *args, **kwargs):

        for pt in self.portal_types:
            attr_name = pt.replace(' ', '_')
            setattr(self, attr_name, self._process_content)

    def _process_content(self, request=None, **kwargs):
        subpath = kwargs.get('subpath', [])
        portal_type = subpath[1] if len(subpath) > 1 else None
        uid = subpath[2] if len(subpath) > 2 else None
        if uid:
            return self.content(portal_type=portal_type, uid=uid)
        else:
            return self.list(portal_type=portal_type)

    @property
    def structure(self):
        structure = {}
        dc_fields = {
            'uri':
            _(u'Content permanent URI'),
            'identifier':
            _(u'Content site address'),
            'uid':
            _(u'Content unique identifier'),
            'title':
            _(u'Dublin Core Title element - resource name.'),
            'description':
            _(u'Dublin Core Description element - resource abstract.'),
            'creator':
            _(u'Dublin Core Creator element - resource author.'),
        }
        for portal_type in self.portal_types:
            # msgid = _(u'dublin_core_conttype_msg', default=u'Dublin Core info for ${type} content type', mapping={u'type': portal_type})
            structure[portal_type] = {
                # 'description': msgid, # FIX: Printing only msgid on /apidata/content
                'description':
                'Dublin Core info for {0} content type'.format(portal_type)
            }
            structure[portal_type]['fields'] = dc_fields.copy()
        return structure

    def _dc_content(self, content):
        """ Returns DC info

        :returns: dictionary with content information
        :rtype: dict
        """
        data = {}
        for key, value in DC_MAPPING.items():
            if value and hasattr(content, value):
                # Using method
                data[key] = getattr(content, value)()
        data['type'] = content.portal_type
        related = content.getRefs()
        data['relation'] = [
            '{0}/{1}/{2}'.format(self.uri, o.portal_type, o.UID())
            for o in related
        ]
        return data

    def content(self, portal_type=None, uid=None):
        """ Returns info about a content

        :returns: dictionary with content information
        :rtype: dict
        """
        data = {}
        if uid:
            try:
                content = api.content.get(UID=uid)
            except ValueError:
                return data
            if content.portal_type == portal_type:
                data = self._dc_content(content)
        return data

    def list(self, portal_type=None):
        """ Returns info about a content

        :returns: dictionary with content information
        :rtype: dict
        """
        ct = api.portal.get_tool('portal_catalog')
        items = []
        results = ct.searchResults(portal_type=portal_type)
        for brain in results:
            uid = brain.UID
            item = {'uid': uid}
            item['identifier'] = brain.getURL()
            # Need to escape portal_type
            item['uri'] = '{0}/{1}/{2}'.format(self.uri, portal_type, uid)
            item['title'] = brain.Title
            item['description'] = brain.Description
            item['creator'] = brain.Creator
            items.append(item)
        return items

    @property
    def dc_properties(self):
        g = rdflib.Graph()
        g.parse("dcelements.rdf")
        properties = g.subjects(RDF['type'], RDF['Property'])
        prop_dict = {}
        for prop in properties:
            prop_dict[prop.split('/')[-1]] = {
                'label': g.value(prop, RDFS['label']),
                'description': g.value(prop, RDFS['comment'])
            }
        return prop_dict
コード例 #41
0
class CookieConsentSettingsEditForm(controlpanel.RegistryEditForm):
    """Media settings form.
    """
    schema = ICookieConsentSettings
    #fields = field.Fields(ICookieBannerSettings)
    groups = (FormCookieConsentBanner, FormOptOut)
    id = "CookieConsentSettingsEditForm"
    label = _(u"Cookie consent configuration")
    description = _(u"Configuration of the cookie consent in the site")

    def cleanHTML(self, data):
        """
        clean text in the given data, so the user can't insert dangerous
        html (for example cross-site scripting)
        """
        pt = api.portal.get_tool('portal_transforms')
        for configuration in data['cookie_consent_configuration']:
            text = configuration.text
            if not text:
                continue
            safe_text = pt.convert('safe_html', text)
            configuration.text = safe_text.getData()

    @button.buttonAndHandler(pmf('Save'), name='save')
    def handleSave(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return
        self.cleanHTML(data)
        self.applyChanges(data)
        IStatusMessage(self.request).addStatusMessage(_(u"Changes saved"),
                                                      "info")
        self.context.REQUEST.RESPONSE.redirect("@@%s" % self.__name__)

    @button.buttonAndHandler(pmf('Cancel'), name='cancel')
    def handleCancel(self, action):
        IStatusMessage(self.request).addStatusMessage(_(u"Changes cancelled"),
                                                      "info")
        self.request.response.redirect(
            "%s/%s" % (self.context.absolute_url(), self.control_panel_view))


#    def updateWidgets(self):
#        super(CookieConsentSettingsEditForm, self).updateWidgets()
#        for main_widget in self.widgets['cookie_consent_configuration'].widgets:
#        for main_widget in self.groups[0].fields['cookie_consent_configuration'].widgets:
#            widgets = main_widget.subform.widgets
#            fix_widget_style(error_widgets['text'])
#            widgets['privacy_link_url'].style = u'width: 100%'
#            widgets['privacy_link_text'].style = u'width: 100%'

    def update(self):
        super(CookieConsentSettingsEditForm, self).update()
        for fieldset in self.groups:
            widgets = fieldset.widgets
            if 'cookie_consent_configuration' in widgets:
                for main_widget in widgets[
                        'cookie_consent_configuration'].widgets:
                    widgets = main_widget.subform.widgets
                    fix_widget_style(widgets['text'])
                    widgets['privacy_link_url'].style = u"width: 100%"
                    widgets['privacy_link_text'].size = 40
                    widgets['dashboard_link_text'].size = 40
            if 'optout_configuration' in widgets:
                for main_widget in widgets['optout_configuration'].widgets:
                    widgets = main_widget.subform.widgets
                    for subwidget in widgets['texts'].widgets:
                        widgets = subwidget.subform.widgets
                        fix_widget_style(widgets['app_description'])
                        widgets['app_title'].style = u"width: 100%"
コード例 #42
0
 def label(self):
     return pmf('tabs_home', default="Home")
コード例 #43
0
ファイル: helper.py プロジェクト: hellfish2/opengever.core
def _linked_document_with_tooltip(item, value, trashed=False):

    data = {}

    if isinstance(value, unicode):
        value = value.encode('utf-8')
    data['value'] = value

    # Determine URL method
    data['url'] = '#'
    if hasattr(item, 'getURL'):
        data['url'] = item.getURL()
    elif hasattr(item, 'absolute_url'):
        data['url'] = item.absolute_url()

    # tooltip links
    data['preview_link'] = '%s/@@download_pdfpreview' % (data['url'])
    data['preview_label'] = translate(base_mf(u'button_pdf', 'PDF'),
                                      context=item.REQUEST).encode('utf-8')

    data['edit_metadata_link'] = '%s/edit_checker' % (data['url'])
    data['edit_metadata_label'] = translate(
        pmf(u'Edit metadata'), context=item.REQUEST).encode('utf-8')

    data['edit_direct_link'] = '%s/editing_document' % (data['url'])
    data['edit_direct_label'] = translate(pmf(u'Checkout and edit'),
                                          context=item.REQUEST).encode('utf-8')

    # Construct CSS class
    data['css_class'] = get_css_class(item)

    # Construct breadcrumbs
    breadcrumb_titles = _breadcrumbs_from_item(item)
    data['breadcrumbs'] = " > ".join(t for t in breadcrumb_titles)

    # Make sure all data used in the HTML snippet is properly escaped
    for k, v in data.items():
        data[k] = cgi.escape(v, quote=True)

    tooltip_links = []

    is_doc = item.portal_type == 'opengever.document.document'

    if is_doc and PDFCONVERTER_AVAILABLE:
        tooltip_links.append("""<a href='%(preview_link)s'>
                    %(preview_label)s
                </a>""" % data)

    if not trashed:
        tooltip_links.append("""<a href='%(edit_metadata_link)s'>
                    %(edit_metadata_label)s
                </a>""" % data)

    if is_doc and not trashed:
        tooltip_links.append("""<a href='%(edit_direct_link)s'>
                    %(edit_direct_label)s
                </a>""" % data)

    data['tooltip_links'] = """
                """.join(tooltip_links)

    link = """<div class='linkWrapper'>
    <a class='tabbedview-tooltip %(css_class)s' href='%(url)s'></a>
    <a href='%(url)s'>%(value)s</a>
    <div class='tabbedview-tooltip-data'>
        <div class='tooltip-content'>
            <div class='tooltip-header'>%(value)s</div>
            <div class='tooltip-breadcrumb'>%(breadcrumbs)s</div>
            <div class='tooltip-links'>
                %(tooltip_links)s
            </div>
        </div>
        <div class='bottomImage'></div>
    </div>
</div>""" % data

    return link