class ModerationPortletAssignment(base.Assignment):
    implements(IModerationPortlet)

    heading = _(u"Feed moderation")
    description = _(u"Use this form to moderate content.")

    title = _(u"Moderation portlet")
Exemple #2
0
class RegistryEditForm(form.EditForm):
    control_panel_view = "plone_control_panel"

    def getContent(self):
        return annotation_proxy(self.context, self.schema)

    @button.buttonAndHandler(_(u"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._redirect()

    @button.buttonAndHandler(_(u"Cancel"), name='cancel')
    def handleCancel(self, action):
        IStatusMessage(self.request).addStatusMessage(
            _(u"Edit cancelled."), "info"
            )

        self._redirect()

    def _redirect(self):
        self.request.response.redirect(
            "%s/%s" % (self.context.absolute_url(),
                       self.control_panel_view)
            )
class CampaignPortletAssignment(base.Assignment):
    implements(ICampaignPortlet)

    heading = _(u"Campaign scheduling")
    description = _(u"Send or schedule a newsletter campaign.")

    title = _(u"Campaign portlet")

    start = None
    section = u"std_content00"

    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            self.__dict__[name] = value
class ISubscriptionPortlet(IPortletDataProvider, ISubscriptionFormSettings):
    heading = schema.TextLine(
        title=_(u"Title"),
        description=_(u"Provide a title for the portlet."),
        required=True,
        default=u"Sign up",
    )

    description = schema.Text(
        title=_(u"Description"),
        description=_(u"Enter a description of your newsletter."),
        required=False,
        default=u"Join our newsletter and stay updated!",
    )
class IFeedControl(Interface):
    """Feed control settings."""

    feeds = schema.Set(
        title=_(u"Feeds"),
        description=_(u"Select one or more items from this list "
                      u"to include in the corresponding feed."),
        required=False,
        value_type=schema.Choice(
            vocabulary="collective.chimpfeed.vocabularies.Feeds",
        )
    )

    feedCategory = schema.Choice(
        title=_(u"Feed category"),
        description=_(u"Please select a category for this item."),
        required=False,
        default=None,
        vocabulary="collective.chimpfeed.vocabularies.Categories",
    )

    feedSchedule = schema.Date(
        title=_(u'Feed date'),
        description=_(u'If this date is set, the content will only be '
                      u'included in Mailchimp-based feeds from this date on. '
                      u'Otherwise, the "Publishing date" is used.'),
        required=False,
    )

    feedModerate = schema.Bool(
        title=_(u'Feed moderation'),
        description=_(u'Select this option to approve item.'),
        required=False,
    )
    def update(self):
        super(CampaignForm, self).update()

        today = datetime.date.today()

        date = self.context.start
        if date is None:
            date = today

        start = self.widgets['start']
        start.value = (date.year, date.month, date.day)

        subject = self.widgets['subject']
        if not subject.value:
            value = self.context.subject or \
                self.context.Title().decode('utf-8')

            subject.value = _(
                u"${subject} ${date}", mapping={
                'subject': value, 'date': ulocalized_time(
                    DateTime(),
                    context=self.context,
                    request=self.request
                ).lstrip('0')}
            )
    def update(self):
        super(CampaignForm, self).update()

        today = datetime.date.today()

        date = self.context.start
        if date is None:
            date = today

        start = self.widgets['start']
        start.value = (date.year, date.month, date.day)

        subject = self.widgets['subject']
        if not subject.value:
            value = self.context.subject or \
                self.context.Title().decode('utf-8')

            subject.value = _(u"${subject} ${date}",
                              mapping={
                                  'subject':
                                  value,
                                  'date':
                                  ulocalized_time(
                                      DateTime(),
                                      context=self.context,
                                      request=self.request).lstrip('0')
                              })
    def update(self):
        super(NewsletterForm, self).update()

        today = datetime.date.today()

        subject = self.widgets['subject']
        if type(subject.value) == type(''):
            subject.value = subject.value.decode('utf-8')
        if not subject.value:
            value = self.context.subject or \
                self.context.Title().decode('utf-8')

            subject.value = _(u"${subject} ${date}",
                              mapping={
                                  'subject':
                                  value,
                                  'date':
                                  ulocalized_time(
                                      DateTime(),
                                      context=self.context,
                                      request=self.request).lstrip('0')
                              })

        if not self.context.select_interest_groups:
            self.widgets['interests'].mode = HIDDEN_MODE
    def get_name(self):
        api = getUtility(IApiUtility, context=self)
        for list_id, name in api.get_lists():
            if list_id == self.mailinglist:
                return name

        return _(u"Untitled")
Exemple #10
0
    def groups(self):
        last = None
        groups = []
        entries = []
        today = DateTime()

        for entry in self.entries:
            date = entry['feedSchedule']

            days = int(math.floor(date - today))
            if days != last:
                entries = []

                # To-Do: Use Plone's date formatters
                if days == -1:
                    name = _(u"Today")
                elif days < 7:
                    abbr = date.strftime("%a")
                    name = translate(
                        'weekday_%s' % abbr.lower(),
                        domain="plonelocales",
                        context=self.request
                        )
                else:
                    name = self._localize_time(date, False)

                groups.append({
                    'date': name,
                    'entries': entries,
                    })

            entries.append(entry)

        return groups
class SubscriptionPortletForm(FormBase):
    name = "Subscribe"

    form_fields = form.Fields(ISubscriptionPortlet)
    description = _(u"This portlet shows a subscription form.")

    def setUpWidgets(self, **kwargs):
        super(SubscriptionPortletForm, self).setUpWidgets(**kwargs)

        widget = self.widgets['mailinglist']
        if len(widget.vocabulary):

            mailinglist = ISubscriptionPortlet.providedBy(self.context) and \
                          self.context.mailinglist or widget.hasInput() \
                          and widget.getInputValue()

            if mailinglist:
                pass
            else:
                # Make a default choice
                token = tuple(widget.vocabulary)[-1].token
                widget.setRenderedValue(token)
        else:
            self.widgets['interest_groups'].hidden = True
            self.widgets['interest_groupings'].hidden = True
    def get_terms(self):
        groupings = self.get_groupings()

        for grouping in groupings:
            value = token = grouping['id']
            groups = grouping['groups']
            name = grouping['name']

            if groups:
                names = [group['name'] for group in groups]

                if len(names) > 4:
                    del names[4:]

                    name = _(
                        u"${name} (${groups} and ${count} more)",
                        mapping={
                            'name': name,
                            'groups': ", ".join(names),
                            'count': len(groups) - len(names),
                            }
                        )
                else:
                    name += u" (%s)" % ", ".join(names)

            yield SimpleTerm(value, token, name)
    def get_name(self):
        api = getUtility(IApiUtility, context=self)
        for list_id, name in api.get_lists():
            if list_id == self.mailinglist:
                return name

        return _(u"Untitled")
    def handleRepair(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        query = Indexed('chimpfeeds')
        brains = self.context.portal_catalog.evalAdvancedQuery(query)

        context = self.getContent()
        vocabulary = feeds_factory(context)
        all_feeds = set(term.value for term in vocabulary)

        count = 0
        bad = set()

        changed = []
        for i, brain in enumerate(brains):
            try:
                feeds = set(brain.chimpfeeds)
            except TypeError:
                continue

            missing = feeds - all_feeds
            bad |= missing

            if missing:
                count += 1
                obj = brain.getObject()
                try:
                    field = obj.getField('feeds')
                except AttributeError:
                    feeds = obj.feeds
                    field = None
                else:
                    feeds = set(field.get(obj))

                fixed = feeds - missing

                if field is None:
                    obj.feeds = fixed
                else:
                    field.set(obj, fixed)

                changed.append(obj)

        for obj in changed:
            modified(obj)
            obj.reindexObject()

        logger.info("Repair complete; %d items updated." % count)
        if bad:
            logger.info("Feeds removed: %s." % (", ".join(bad).encode('utf-8')))

        IStatusMessage(self.request).addStatusMessage(
            _(u"Repaired ${count} items.", mapping={'count': count}),
            "info"
        )
class ICampaign(ICampaignPortlet):
    """Note that most fields are inherited from the portlet."""

    limit = schema.Bool(
        title=_(u"Limit"),
        description=_(u"Include scheduled items up until today's date only."),
        default=True,
        required=False,
    )

    filtering = schema.Bool(
        title=_(u"Apply filtering markup"),
        description=_(u"Select this option to apply the markup "
                      u"required for automatic interest group "
                      u"filtering."),
        default=True,
        required=False,
    )

    create_draft = schema.Bool(title=_(u"Create new campaigns as drafts"),
                               required=False,
                               default=True)

    schedule = schema.Datetime(
        title=_(u"Schedule date"),
        description=_(u"If provided, item will be scheduled to be sent "
                      u"at this time."),
        required=False,
        default=None,
    )
 def description(self):
     context = self.context.aq_base
     if self.request.get('success'):
         return u''
     elif not IPloneSiteRoot.providedBy(context) \
              and context.Description():
         return context.Description()
     else:
         return _(u"Select subscription options and submit form.")
Exemple #17
0
    def handleRepair(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        query = Indexed('chimpfeeds')
        brains = self.context.portal_catalog.evalAdvancedQuery(query)

        context = self.getContent()
        vocabulary = feeds_factory(context)
        all_feeds = set(term.value for term in vocabulary)

        count = 0
        bad = set()

        changed = []
        for i, brain in enumerate(brains):
            try:
                feeds = set(brain.chimpfeeds)
            except TypeError:
                continue

            missing = feeds - all_feeds
            bad |= missing

            if missing:
                count += 1
                obj = brain.getObject()
                try:
                    field = obj.getField('feeds')
                except AttributeError:
                    feeds = obj.feeds
                    field = None
                else:
                    feeds = set(field.get(obj))

                fixed = feeds - missing

                if field is None:
                    obj.feeds = fixed
                else:
                    field.set(obj, fixed)

                changed.append(obj)

        for obj in changed:
            modified(obj)
            obj.reindexObject()

        logger.info("Repair complete; %d items updated." % count)
        if bad:
            logger.info("Feeds removed: %s." %
                        (", ".join(bad).encode('utf-8')))

        IStatusMessage(self.request).addStatusMessage(
            _(u"Repaired ${count} items.", mapping={'count': count}), "info")
 def description(self):
     context = self.context.aq_base
     if self.request.get('success'):
         return u''
     elif not IPloneSiteRoot.providedBy(context) \
              and context.Description():
         return context.Description()
     else:
         return _(u"Select subscription options and submit form.")
class CampaignPortletAddForm(base.AddForm):
    label = _(u"Add campaign portlet")
    form_fields = form.Fields(ICampaignPortlet)

    # Let's not ask the user to name a start date on adding the
    # portlet.
    form_fields = form_fields.omit('start')

    def create(self, data):
        return CampaignPortletAssignment(**data)
class IControlPanel(IFeedSettings):
    urls = schema.Tuple(
        title=_(u"RSS"),
        description=_(u"This field lists an RSS-feed for each of "
                      u"the available feed strings (including "
                      u"those that are automatically pulled from "
                      u"interest groups."),
        required=False,
        value_type=schema.ASCIILine(),
    )

    lists = schema.Tuple(
        title=_(u"Lists"),
        description=_(u"This listing shows a link to a "
                      u"subscription form for each of the defined "
                      u"lists in your account."),
        required=False,
        value_type=schema.ASCIILine(),
    )
class NewsletterPortletAssignment(base.Assignment):
    implements(INewsletterPortlet)

    heading = _(u"Static campaign scheduling")
    description = _(
        u"Send or schedule a newsletter campaign based on the current context."
    )

    title = _(u"Newsletter portlet")

    maillinglist = ''
    interest_groups = tuple()
    select_interest_groups = False
    template = ''
    section = u"std_content00"
    subject = ''

    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            self.__dict__[name] = value
Exemple #22
0
    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._redirect()
class ISubscription(Interface):
    email = schema.TextLine(
        title=_(u"E-mail"),
        required=True,
        constraint=is_email,
    )

    interests = schema.Tuple(
        value_type=schema.Choice(
            vocabulary="collective.chimpfeed.vocabularies.InterestGroups", ),
        required=False,
        constraint=interests_required,
    )
    def groups(self):
        last = None
        groups = []
        entries = []
        today = DateTime()
        today = DateTime(today.year(), today.month(), today.day())

        for entry in self.entries:
            date = entry['feedSchedule']
            days = int(math.floor(date - today))
            if days != last:
                entries = []

                # To-Do: Use Plone's date formatters
                if days == -1:
                    name = _(u"Today")
                else:
                    abbr = date.strftime("%a")
                    name = translate(
                        'weekday_%s' % abbr.lower(),
                        domain="plonelocales",
                        context=self.request
                    ).capitalize()

                    if days < 0 or days >= 7:
                        name = _(u"${subject} ${date}", mapping={
                            'subject': name,
                            'date': self._localize_time(date, False),
                        })

                groups.append({
                    'date': name,
                    'entries': entries,
                })

            last = days
            entries.append(entry)

        return groups
 def fields(self):
     fields = field.Fields()
     settings = IFeedSettings(self.context)
     if settings.show_name:
         fields += field.Fields(
             schema.TextLine(
                 __name__="name",
                 title=_(u"Name"),
                 required=False,
             ))
     fields += field.Fields(ISubscription)
     fields['interests'].widgetFactory = InterestsWidget.factory
     return fields
    def groups(self):
        last = None
        groups = []
        entries = []
        today = DateTime()
        today = DateTime(today.year(), today.month(), today.day())

        for entry in self.entries:
            date = entry['feedSchedule']
            days = int(math.floor(date - today))
            if days != last:
                entries = []

                # To-Do: Use Plone's date formatters
                if days == -1:
                    name = _(u"Today")
                else:
                    abbr = date.strftime("%a")
                    name = translate('weekday_%s' % abbr.lower(),
                                     domain="plonelocales",
                                     context=self.request).capitalize()

                    if days < 0 or days >= 7:
                        name = _(u"${subject} ${date}",
                                 mapping={
                                     'subject': name,
                                     'date': self._localize_time(date, False),
                                 })

                groups.append({
                    'date': name,
                    'entries': entries,
                })

            last = days
            entries.append(entry)

        return groups
 def fields(self):
     fields = field.Fields()
     settings = IFeedSettings(self.context)
     if settings.show_name:
         fields += field.Fields(
             schema.TextLine(
                 __name__="name",
                 title=_(u"Name"),
                 required=False,
             )
         )
     fields += field.Fields(ISubscription)
     fields['interests'].widgetFactory = InterestsWidget.factory
     return fields
    def handleCreate(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        success = self.process("campaignCreate", **data)

        if success:
            IStatusMessage(self.request).addStatusMessage(
                _(u"Campaign created."), "info")

            # Set date to tomorrow's date.
            self.context.start = datetime.date.today() + \
                datetime.timedelta(days=1)
class INewsletter(INewsletterPortlet):
    """Note that most fields are inherited from the portlet."""

    interests = schema.Tuple(
        title=_(u"Select interest groups"),
        description=_(u"If no interest groups are selected the predefined "
                      u"groups will be used, which were specified during the "
                      u"creation of the portlet"),
        value_type=schema.Choice(
            vocabulary="collective.chimpfeed.vocabularies.InterestGroups", ),
        required=False,
    )

    create_draft = schema.Bool(title=_(u"Create new campaigns as drafts"),
                               required=False,
                               default=True)

    schedule = schema.Datetime(
        title=_(u"Schedule date"),
        description=_(u"If provided, item will be scheduled to be sent "
                      u"at this time."),
        required=False,
        default=None,
    )
    def handleCreate(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        success = self.process("campaignCreate", **data)

        if success:
            IStatusMessage(self.request).addStatusMessage(
                _(u"Campaign created."),
                "info"
            )

            # Set date to tomorrow's date.
            self.context.start = datetime.date.today() + \
                datetime.timedelta(days=1)
    def handleCreate(self, action):
        if self.context.REQUEST.get('restricted_traverse', False):
            return
        subj = self.context.REQUEST.get('chimpXYZ.widgets.subject')
        if type(subj) == type(''):
            self.context.REQUEST.set('chimpXYZ.widgets.subject',
                                     subj.decode('utf-8'))
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        if not self.context.select_interest_groups:
            data.update(dict(interests=self.context.interest_groups))
        success = self.process("campaignCreate", **data)

        if success:
            IStatusMessage(self.request).addStatusMessage(
                _(u"Campaign created."), "info")
    def template(self):
        site = getToolByName(self.context, "portal_url").getPortalObject()
        settings = IFeedSettings(site)
        api_key = settings.mailchimp_api_key

        if not api_key:
            return

        try:
            api = greatape.MailChimp(api_key, debug=False)
            cid = self.request.get('cid', '')
            content = api(method="campaignContent", cid=cid)
        except greatape.MailChimpError:
            IStatusMessage(self.request).addStatusMessage(
                _(u"Unable to show content."), "error"
                )
            return

        return content['html']
    def handleCreate(self, action):
        if self.context.REQUEST.get('restricted_traverse', False):
            return
        subj = self.context.REQUEST.get('chimpXYZ.widgets.subject')
        if type(subj) == type(''):
            self.context.REQUEST.set('chimpXYZ.widgets.subject', subj.decode('utf-8'))
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        if not self.context.select_interest_groups:
            data.update(dict(interests=self.context.interest_groups))
        success = self.process("campaignCreate", **data)

        if success:
            IStatusMessage(self.request).addStatusMessage(
                _(u"Campaign created."),
                "info"
            )
class ISubscriptionFormSettings(Interface):
    mailinglist = schema.Choice(
        title=_(u"Mailinglist"),
        description=_(u"Select a mailinglist for this portlet."),
        vocabulary="collective.chimpfeed.vocabularies.Lists",
        required=True,
    )

    interest_groupings = schema.Tuple(
        title=_(u"Interest groups"),
        description=_(u"Select interest groups. "
                      u"Note that all interests within the selected "
                      u"groups will appear in the portlet."),
        value_type=schema.Choice(
            vocabulary="collective.chimpfeed.vocabularies.InterestGroupings",
        ),
        required=False,
    )

    interest_groups = schema.Tuple(
        title=_(u"Interests"),
        description=_(u"Select interests."),
        value_type=schema.Choice(
            vocabulary="collective.chimpfeed.vocabularies.InterestGroups",
        ),
        required=False,
    )

    preselected_interest_groups = schema.Tuple(
        title=_(u"Preselected interests."),
        description=_(u"If interests is selected here, the interests groups will be preselected, "
                      u"and the user will not be able to select these."),
        value_type=schema.Choice(
            vocabulary="collective.chimpfeed.vocabularies.InterestGroups",
        ),
        required=False,
    )
    def process(self,
                method,
                subject=None,
                create_draft=False,
                schedule=None,
                **data):
        settings = IFeedSettings(self.context)
        api_key = settings.mailchimp_api_key

        view = getMultiAdapter((self.context.aq_parent, self.request),
                               name="chimpfeed-campaign")

        params = self.makeParams(**data)
        rendered = view.template(**params).encode('utf-8')
        next_url = self.request.get('HTTP_REFERER') or self.action

        segments = view.getSegments(**params).items()
        if segments:
            segment_opts = {
                'match':
                'all',
                'conditions': [{
                    'field': 'interests-%s' % groupingid,
                    'op': 'one',
                    'value': groupids
                } for groupingid, groupids in segments[:10]]
            }

            if len(segments) > 10:
                count = len(segments) - 10
                IStatusMessage(self.request).addStatusMessage(
                    _(u"%d segments were ignored "
                      u"(Mailchimp limits this to 10)." % count), "warning")
        else:
            segment_opts = {}

        return self.createCampaign(api_key, method, subject, create_draft,
                                   schedule, rendered, next_url, segment_opts)
Exemple #36
0
    def renderInterestGroupings(self):
        filtered = (
            grouping for grouping in self.groupings
            if grouping['id'] in self.context.interest_groupings
            )

        rendered = []

        for grouping in filtered:
            terms = tuple(interest_groups_factory.get_terms_for_grouping(
                grouping, count=False
                ))

            # Create label from the grouping name; we simply lowercase
            # it.
            label = _(u"Choose ${name}:", mapping={
                'name': cgi.escape(grouping['name'].lower())
                })

            result = self.renderChoices(terms, label)
            rendered.append(result)

        return u"\n".join(rendered)
    def update(self):
        super(NewsletterForm, self).update()

        today = datetime.date.today()

        subject = self.widgets['subject']
        if type(subject.value) == type(''):
            subject.value = subject.value.decode('utf-8')
        if not subject.value:
            value = self.context.subject or \
                self.context.Title().decode('utf-8')

            subject.value = _(
                u"${subject} ${date}", mapping={
                'subject': value, 'date': ulocalized_time(
                    DateTime(),
                    context=self.context,
                    request=self.request
                ).lstrip('0')}
            )

        if not self.context.select_interest_groups:
            self.widgets['interests'].mode = HIDDEN_MODE
Exemple #38
0
    def get_terms(self):
        groupings = self.get_groupings()

        for grouping in groupings:
            value = token = grouping['id']
            groups = grouping['groups']
            name = grouping['name']

            if groups:
                names = [group['name'] for group in groups]

                if len(names) > 4:
                    del names[4:]

                    name = _(u"${name} (${groups} and ${count} more)",
                             mapping={
                                 'name': name,
                                 'groups': ", ".join(names),
                                 'count': len(groups) - len(names),
                             })
                else:
                    name += u" (%s)" % ", ".join(names)

            yield SimpleTerm(value, token, name)
    def process(self, method, subject=None,
                create_draft=False, schedule=None, **data):
        settings = IFeedSettings(self.context)
        api_key = settings.mailchimp_api_key

        view = getMultiAdapter(
            (self.context.aq_parent, self.request), name="chimpfeed-campaign"
        )

        params = self.makeParams(**data)
        rendered = view.template(**params).encode('utf-8')
        next_url = self.request.get('HTTP_REFERER') or self.action

        segments = view.getSegments(**params).items()
        if segments:
            segment_opts = {
                'match': 'all',
                'conditions':
                [{'field': 'interests-%s' % groupingid,
                  'op':'one',
                  'value': groupids}
                 for groupingid, groupids in segments[:10]
                 ]}

            if len(segments) > 10:
                count = len(segments) - 10
                IStatusMessage(self.request).addStatusMessage(
                    _(u"%d segments were ignored "
                      u"(Mailchimp limits this to 10)." % count),
                    "warning"
                )
        else:
            segment_opts = {}

        return self.createCampaign(api_key, method, subject, create_draft,
                                   schedule, rendered, next_url, segment_opts)
class CampaignView(BrowserView):
    template = ViewPageTemplateFile('campaign.pt')

    title = _(u"Preview")

    def results(self, start, until=None):
        today = DateTime()
        today = DateTime(today.year(), today.month(), today.day())
        start = DateTime(start)
        start = DateTime(start.year(), start.month(), start.day())

        query = Indexed('chimpfeeds') & \
                In('review_state', ('published', )) & \
                Ge('feedSchedule', start)

        if until:
            try:
                until = DateTime(until)
            except DateTime.SyntaxError:
                pass
            else:
                query = query & Le('feedSchedule', until)

        site = getToolByName(self.context, "portal_url").getPortalObject()
        settings = IFeedSettings(site)
        if settings.use_moderation:
            query = query & Eq('feedModerate', True)

        catalog = getToolByName(self.context, "portal_catalog")

        extras = []
        utilities = getUtilitiesFor(IGroupExtras)
        groups = InterestGroupVocabulary()(self.context)
        for name, util in utilities:
            for group in groups:
                extras.extend(util.items(group.title, start, until))

        return list(catalog.evalAdvancedQuery(
            query, (('feedSchedule', 'desc'), ))) + extras
        

    def getGroupings(self, start, until=None):
        groupings = {}
        for brain in self.results(start, until=until):

            # Note that an item can appear in more than one group.
            categories = [name.rsplit(':', 1)[0] for name in brain.chimpfeeds]
            for category in set(categories):
                items = groupings.setdefault(category, [])
                items.append(brain)

        sorting = queryUtility(IGroupSorter)
        if sorting is None:
            key = lambda name, items: name
        else:
            key = sorting.key

        return sorted(groupings.items(), key=lambda item: key(*item))

    def getSegments(self, start, until=None, **kwargs):
        chimpfeeds = set()
        for brain in self.results(start, until=until):
            chimpfeeds.update(
                (feed.replace(' ', '') for feed in brain.chimpfeeds)
            )

        segments = {}
        
        for term in InterestGroupVocabulary()(self.context):
            if term.title.replace(' ', '') in chimpfeeds:
                groupingid, grouptitle, groupid = term.value
                items = segments.setdefault(groupingid, [])
                items.append(groupid)
                
        return segments
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        settings = IFeedSettings(self.context)
        api_key = settings.mailchimp_api_key
        next_url = self.nextURL()

        try:
            list_id = (data.pop('list_id', None)
                       or self.getContent().mailinglist)
            try:
                name = data.pop('name')
            except KeyError:
                name = ''
            email = data.pop('email')
            interests = data.pop('interests')

            content = self.getContent()

            preselected = getattr(content, 'preselected_interest_groups', None)
            if preselected:
                if not interests:
                    interests = preselected
                else:
                    interests = interests + preselected

            if api_key:
                api = greatape.MailChimp(api_key, debug=False)

                # Negotiate language
                language = negotiate(self.request)

                # Split full name into first (given) and last name.
                try:
                    fname, lname = queryUtility(
                        INameSplitter,
                        name=language,
                        default=GenericNameSplitter).split_name(name)
                except AttributeError:
                    fname, lname = u'', u''

                # Log subscription attempt.
                logger.info(("listSubscribe(%r, %r, %r, %r)" %
                             (list_id, email, fname, lname)).encode('utf-8'))

                merge_vars = {
                    'FNAME':
                    fname.encode('utf-8'),
                    'LNAME':
                    lname.encode('utf-8'),
                    'GROUPINGS': [
                        dict(
                            id=grouping_id,
                            groups=",".join(
                                group.encode('utf-8').replace(',', '\\,')
                                for group in group_names),
                        ) for (grouping_id, group_names
                               ) in create_groupings(interests).items()
                    ]
                }

                for name, value in data.items():
                    if value is not None:
                        merge_vars[name.upper()] = value.encode('utf-8')

                try:
                    result = api(method="listSubscribe",
                                 id=list_id,
                                 email_address=email,
                                 update_existing=True,
                                 replace_interests=False,
                                 merge_vars=merge_vars)
                except greatape.MailChimpError, exc:
                    logger.warn(exc.msg)

                    # ... is not a valid interest grouping id for the list
                    if exc.code == 270:
                        return IStatusMessage(self.request).addStatusMessage(
                            _(u"There was a problem signing you up for "
                              u"the selected interest groups. This could "
                              u"mean that the subscription service is "
                              u"configured incorrectly. Please contact "
                              u"the webmaster."),
                            "error",
                        )
                else:
                    if result:
                        next_url += ('?' in next_url and '&'
                                     or '?') + 'success=yes'

                        return IStatusMessage(self.request).addStatusMessage(
                            _(u"Thank you for signing up. We'll send you a "
                              u"confirmation message by e-mail shortly."),
                            "info")

            IStatusMessage(self.request).addStatusMessage(
                _(
                    u"An error occurred while processing your "
                    u"request to sign up for ${email}. "
                    u"Please try again!",
                    mapping={'email': email}), "error")
Exemple #42
0
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        settings = IFeedSettings(self.context)
        api_key = settings.mailchimp_api_key

        try:
            list_id = self.context.mailinglist

            email = data['email']
            name = data['name']
            interests = data['interests']

            if api_key:
                api = greatape.MailChimp(api_key, debug=False)

                # Negotiate language
                language = negotiate(self.request)

                # Split full name into first (given) and last name.
                fname, lname = queryUtility(
                    INameSplitter, name=language, default=GenericNameSplitter
                    ).split_name(name)

                try:
                    result = api(
                        method="listSubscribe", id=list_id,
                        email_address=email,
                        update_existing=True,
                        replace_interests=False,
                        merge_vars={
                            'FNAME': fname.encode('utf-8'),
                            'LNAME': lname.encode('utf-8'),
                            'GROUPINGS': [
                                dict(
                                    id=grouping_id,
                                    groups=",".join(
                                        group.\
                                        encode('utf-8').\
                                        replace(',', '\\,')
                                        for group in group_names
                                        ),
                                    )
                                for (grouping_id, group_names) in
                                create_groupings(interests).items()
                                ]
                            },
                        )
                except greatape.MailChimpError, exc:
                    logger.warn(exc.msg)
                else:
                    if result:
                        return IStatusMessage(self.request).addStatusMessage(
                            _(u"Thank you for signing up. We'll send you a "
                              u"confirmation message by e-mail shortly."),
                            "info"
                            )

            IStatusMessage(self.request).addStatusMessage(
                _(u"An error occurred while processing your "
                  u"request to sign up for ${email}. "
                  u"Please try again!", mapping={'email': email}),
                "error")
    def get_terms(self):
        yield SimpleTerm(u"", "", _(u"Empty"))

        for value, name in self.get_templates():
            yield SimpleTerm(value, value, name)
    def handleApprove(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        catalog = self.context.portal_catalog
        bumped = []
        today = datetime.date.today()

        uids = []
        for rid in data['items'] or ():
            metadata = catalog.getMetadataForRID(rid)
            uids.append(metadata['UID'])

        settings = IFeedSettings(self.context)

        brains = catalog.unrestrictedSearchResults(UID=uids)
        for brain in brains:
            obj = brain.getObject()

            # Bump the scheduled date to today's date. This ensures that
            # the item will be shown on the moderation portlet.
            try:
                date = obj.getField('feedSchedule').get(obj)
                if date is not None:
                    date = date.asdatetime().date()
            except AttributeError:
                date = obj.feedSchedule

            if settings.bump_date_on_moderation and (date is None or date < today):
                try:
                    field = obj.getField('feedSchedule')
                except AttributeError:
                    obj.feedSchedule = today
                else:
                    field.set(obj, DateTime(
                        today.year, today.month, today.day
                    ))

                bumped.append(obj)

            try:
                field = obj.getField('feedModerate')
            except AttributeError:
                obj.feedModerate = True
            else:
                field.set(obj, True)

            # Reindex entire object (to make sure the metadata is
            # updated, too).
            obj.reindexObject()

        if data['items']:
            self.widgets['items'].update()

        if bumped:
            IStatusMessage(self.request).addStatusMessage(
                _(u"The scheduled date has been set to today's date "
                  u"for the following items that were scheduled to "
                  u"a date in the past: ${titles}.",
                  mapping={'titles': u', '.join(
                      [obj.Title().decode('utf-8') for obj in bumped])}),
                "info",
            )
Exemple #45
0
 def render(self):
     return _(self.error.__doc__)
            return not settings.use_moderation

    moderation_enabled = moderation_enabled()

    class settings_available:
        def __nonzero__(self):
            context = getSite()
            return IFeedSettings(context, None) is None

    settings_available = settings_available()

    IFeedControl.setTaggedValue(WRITE_PERMISSIONS_KEY, {"feedModerate": MODERATE_PERMISSION})

    IFeedControl.setTaggedValue(
        OMITTED_KEY,
        (
            (IAutoExtensibleForm, "feeds", settings_available),
            (IAutoExtensibleForm, "feedModerate", settings_available),
            (IAutoExtensibleForm, "feedSchedule", settings_available),
            (IAutoExtensibleForm, "feedModerate", moderation_enabled),
        ),
    )

    IFeedControl.setTaggedValue(
        FIELDSETS_KEY,
        [
            Fieldset("dates", fields=["feedSchedule", "feedModerate"], label=_(u"Dates")),
            Fieldset("categorization", fields=["feeds"], label=_(u"Categorization")),
        ],
    )
    def fields(self):
        fields = field.Fields()
        settings = IFeedSettings(self.context)

        # Javascript-widget
        if settings.enable_select_all:
            fields += field.Fields(SelectAllGroupsJavascript(schema.Field(
                __name__="js", required=False), mode="hidden"))

        # Include form fields, but change the order around.
        fields += field.Fields(ISubscription).select('interests')
        fields['interests'].widgetFactory = InterestsWidget.factory

        if settings.show_name:
            fields += field.Fields(
                schema.TextLine(
                    __name__="name",
                    title=_(u"Name"),
                    required=False,
                )
            )

        fields += field.Fields(ISubscription).select('email')

        # Add mailinglist as hidden field
        fields += field.Fields(schema.ASCII(
            __name__="list_id",
            required=True),
            mode="hidden"
        )

        context = self.getContent()
        api = getUtility(IApiUtility, context=self.context)
        result = api.list_merge_vars(context.mailinglist)

        for entry in result:
            name = entry['tag'].lower()

            if name in fields:
                continue

            if not entry['show']:
                continue

            # Skip all-uppercase:
            if entry['name'] == entry['name'].upper():
                continue

            field_type = entry['field_type']
            required = entry['req']

            if field_type == 'text':
                factory = schema.TextLine
                options = {}

            elif field_type == 'dropdown':
                factory = schema.Choice
                choices = list(entry['choices'])

                if not required:
                    choices.append(u"")
                    required = True

                options = {
                    'vocabulary': SimpleVocabulary([
                        SimpleTerm(value=value,
                                   token=value.encode(
                                       'ascii',
                                       'xmlcharrefreplace'),
                                   title=value or _(u"None"))
                        for value in choices])
                }

            else:
                continue

            fields += field.Fields(factory(
                __name__=name.encode('utf-8'),
                default=entry['default'],
                required=required,
                title=_(entry['name']),
                **options
            ))

        return fields
Exemple #48
0
class ControlPanelEditForm(controlpanel.RegistryEditForm):
    schema = IFeedSettings
    fields = field.Fields(IControlPanel)

    label = _(u"MailChimp settings")
    description = _(u"Please configure an API-key and define one or more "
                    u"feeds.")

    fields['urls'].mode = "display"
    fields['urls'].widgetFactory = UrlsWidget.factory

    fields['lists'].mode = "display"
    fields['lists'].widgetFactory = UrlsWidget.factory

    if textlines is not None:
        fields['feeds'].widgetFactory = textlines.TextLinesFieldWidget

    buttons = button.Buttons()
    buttons += controlpanel.RegistryEditForm.buttons
    handlers = controlpanel.RegistryEditForm.handlers.copy()

    def updateActions(self):
        # This prevents a redirect to the main control panel page
        self.request.response.setStatus(200, lock=True)

        super(ControlPanelEditForm, self).updateActions()

    def render(self):
        if switch_on is not None:
            switch_on(self)

        urls = self.widgets['urls']
        urls.update()

        if not urls.value:
            del self.widgets['urls']

        return super(ControlPanelEditForm, self).render()

    def getContent(self):
        content = super(ControlPanelEditForm, self).getContent()
        return ImplicitAcquisitionWrapper(content, self.context)

    @button.buttonAndHandler(_(u"Repair"), name='repair')
    def handleRepair(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        query = Indexed('chimpfeeds')
        brains = self.context.portal_catalog.evalAdvancedQuery(query)

        context = self.getContent()
        vocabulary = feeds_factory(context)
        all_feeds = set(term.value for term in vocabulary)

        count = 0
        bad = set()

        changed = []
        for i, brain in enumerate(brains):
            try:
                feeds = set(brain.chimpfeeds)
            except TypeError:
                continue

            missing = feeds - all_feeds
            bad |= missing

            if missing:
                count += 1
                obj = brain.getObject()
                try:
                    field = obj.getField('feeds')
                except AttributeError:
                    feeds = obj.feeds
                    field = None
                else:
                    feeds = set(field.get(obj))

                fixed = feeds - missing

                if field is None:
                    obj.feeds = fixed
                else:
                    field.set(obj, fixed)

                changed.append(obj)

        for obj in changed:
            modified(obj)
            obj.reindexObject()

        logger.info("Repair complete; %d items updated." % count)
        if bad:
            logger.info("Feeds removed: %s." %
                        (", ".join(bad).encode('utf-8')))

        IStatusMessage(self.request).addStatusMessage(
            _(u"Repaired ${count} items.", mapping={'count': count}), "info")
    def handleApply(self, action):
        data, errors = self.extractData()
        if errors:
            self.status = self.formErrorsMessage
            return

        settings = IFeedSettings(self.context)
        api_key = settings.mailchimp_api_key
        next_url = self.nextURL()

        try:
            list_id = (
                data.pop('list_id', None) or
                self.getContent().mailinglist
            )
            try:
                name = data.pop('name')
            except KeyError:
                name = ''
            email = data.pop('email')
            interests = data.pop('interests')

            content = self.getContent()

            preselected = getattr(content, 'preselected_interest_groups', None)
            if preselected:
                if not interests:
                    interests = preselected
                else:
                    interests = interests + preselected

            if api_key:
                api = greatape.MailChimp(api_key, debug=False)

                # Negotiate language
                language = negotiate(self.request)

                # Split full name into first (given) and last name.
                try:
                    fname, lname = queryUtility(
                        INameSplitter, name=language,
                        default=GenericNameSplitter
                        ).split_name(name)
                except AttributeError:
                    fname, lname = u'', u''

                # Log subscription attempt.
                logger.info(("listSubscribe(%r, %r, %r, %r)" % (
                    list_id, email, fname, lname)).encode('utf-8'))

                merge_vars = {
                    'FNAME': fname.encode('utf-8'),
                    'LNAME': lname.encode('utf-8'),
                    'GROUPINGS': [
                        dict(
                            id=grouping_id,
                            groups=",".join(
                                group.
                                encode('utf-8').
                                replace(',', '\\,')
                                for group in group_names
                            ),
                        )
                        for (grouping_id, group_names) in
                        create_groupings(interests).items()
                    ]
                }

                for name, value in data.items():
                    if value is not None:
                        merge_vars[name.upper()] = value.encode('utf-8')

                try:
                    result = api(
                        method="listSubscribe", id=list_id,
                        email_address=email,
                        update_existing=True,
                        replace_interests=False,
                        merge_vars=merge_vars
                    )
                except greatape.MailChimpError, exc:
                    logger.warn(exc.msg)

                    # ... is not a valid interest grouping id for the list
                    if exc.code == 270:
                        return IStatusMessage(self.request).addStatusMessage(
                            _(u"There was a problem signing you up for "
                              u"the selected interest groups. This could "
                              u"mean that the subscription service is "
                              u"configured incorrectly. Please contact "
                              u"the webmaster."),
                            "error",
                        )
                else:
                    if result:
                        next_url += ('?' in next_url
                                     and '&' or '?') + 'success=yes'

                        return IStatusMessage(self.request).addStatusMessage(
                            _(u"Thank you for signing up. We'll send you a "
                              u"confirmation message by e-mail shortly."),
                            "info"
                        )

            IStatusMessage(self.request).addStatusMessage(
                _(u"An error occurred while processing your "
                  u"request to sign up for ${email}. "
                  u"Please try again!", mapping={'email': email}),
                "error")
 def title(self):
     return _("Subscribe: ${title}", mapping={'title': self.heading})
    IFeedControl.setTaggedValue(
        OMITTED_KEY, (
            (IAutoExtensibleForm, 'feeds', settings_available),
            (IAutoExtensibleForm, 'feedModerate', settings_available),
            (IAutoExtensibleForm, 'feedSchedule', settings_available),
            (IAutoExtensibleForm, 'feedModerate', moderation_enabled),
        )
    )

    IFeedControl.setTaggedValue(
        FIELDSETS_KEY,
        [Fieldset(
            'dates',
            fields=['feedSchedule', 'feedModerate'],
            label=_(u"Dates")),
         Fieldset(
             'categorization',
             fields=['feeds'],
             label=_(u"Categorization")),
         ]
    )

    IFeedControl.setTaggedValue(
        WIDGETS_KEY,
        {'feeds':
         'z3c.form.browser.checkbox.CheckBoxFieldWidget'}
    )


class IGroupExtras(Interface):
    def createCampaign(self, api_key, method, subject,
                       create_draft, schedule, rendered, next_url,
                       segment_opts={}):
        try:
            if not rendered.strip():
                IStatusMessage(self.request).addStatusMessage(
                    _(u"No content found; newsletter not created."),
                    "info"
                )

                return

            if api_key:
                api = greatape.MailChimp(api_key, debug=False)

                try:
                    for entry in api(method="lists"):
                        if entry['id'] == self.context.mailinglist:
                            break
                    else:
                        IStatusMessage(self.request).addStatusMessage(
                            _(u"Mailinglist not found."),
                            "error"
                        )

                        return

                    if self.context.template:
                        section = 'html_%s' % self.context.section
                    else:
                        section = 'html'

                    args = {}

                    args['method'] = method
                    args['type'] = 'regular'
                    args['content'] = {section: rendered}
                    if segment_opts:
                        args['segment_opts'] = segment_opts

                    options = {}
                    options['subject'] = subject.encode("utf-8") or \
                        entry['default_subject']
                    options['from_email'] = entry['default_from_email']
                    options['from_name'] = \
                        entry['default_from_name'].encode("utf-8")
                    options['to_email'] = 0
                    options['list_id'] = self.context.mailinglist
                    options['template_id'] = self.context.template or None
                    options['generate_text'] = True

                    args['options'] = options

                    result = api(**args)

                    if result:
                        if not create_draft:
                            if schedule:
                                # Apply local time zone to get GMT
                                schedule = schedule + datetime.timedelta(
                                    seconds=time.timezone
                                )

                                # Format time
                                schedule_time = time.strftime(
                                    "%Y-%m-%d %H:%M:%S", schedule.utctimetuple()
                                )

                                schedule = api(
                                    method="campaignSchedule",
                                    cid=result,
                                    schedule_time=schedule_time,
                                )

                                if not schedule:
                                    IStatusMessage(self.request).addStatusMessage(
                                        _(u"Campaign created, but not scheduled."),
                                        "error"
                                    )

                                    return
                            else:
                                api(method="campaignSendNow",
                                    cid=result)

                        next_url = self.context.portal_url() + \
                            "/@@chimpfeed-content?cid=%s" % result

                except greatape.MailChimpError, exc:
                    IStatusMessage(self.request).addStatusMessage(
                        _(u"Unable to process request: ${message}",
                          mapping={'message': exc.msg}), "error"
                    )
                    logger.warn(exc.msg)
                    logger.warn(pprint.pformat(args))
                    return

                return bool(result)
        finally:
            self.request.response.redirect(next_url)
Exemple #53
0
    def handleCancel(self, action):
        IStatusMessage(self.request).addStatusMessage(
            _(u"Edit cancelled."), "info"
            )

        self._redirect()
    def label(self):
        if self.request.get('success'):
            return _(u"Request processed")

        name = self.getContent().name
        return _(u"Subscribe to: ${name}", mapping={'name': name})