Beispiel #1
0
 def toLocalizedTime(self,
                     time=None,
                     long_format=None,
                     time_only=None,
                     event=None,
                     startend="start"):
     if not event:
         return self.context.restrictedTraverse("@@plone").toLocalizedTime(
             time, long_format, time_only)
     if ICatalogBrain.providedBy(event):
         event = event.getObject()
     if not IEvent.providedBy(event):
         return self.context.restrictedTraverse("@@plone").toLocalizedTime(
             time, long_format, time_only)
     rs = RecurrenceSupport(event)
     occurences = [
         occ for occ in rs.occurrences(datetime.today())
         if IEvent.providedBy(occ)
     ]
     if len(occurences) >= 1:
         # do not get object which started in the past
         if startend == "start":
             time = getattr(occurences[0], "start")
         elif startend == "end":
             time = getattr(occurences[-1], "end")
     return self.context.restrictedTraverse("@@plone").toLocalizedTime(
         time, long_format, time_only)
Beispiel #2
0
def EventTypes(context):
    """ Vocabulary for available event types.

    Insane stuff: All types are created temporary and checked if the provide
    the IEvent interface. At least, this function is cached forever the Zope
    process lives.
    """
    # TODO: I'd love to query the factory for types, who's instances are
    # implementing a specific interface via the portal_factory API.

    portal = getSite()
    tmp_folder_id = 'event_types_temp_folder__%s' % random.randint(0, 99999999)
    portal.invokeFactory('Folder', tmp_folder_id)
    try:
        tmp_folder = portal._getOb(tmp_folder_id)
        portal_types = getToolByName(portal, 'portal_types')
        all_types = portal_types.listTypeInfo(portal)
        event_types = []
        cnt = 0
        for fti in all_types:
            if not getattr(fti, 'global_allow', False):
                continue
            cnt += 1
            tmp_id = 'temporary__event_types__%s' % cnt
            tmp_obj = None
            fti.constructInstance(tmp_folder, tmp_id)
            tmp_obj = tmp_folder._getOb(tmp_id)
            if tmp_obj:
                if IEvent.providedBy(tmp_obj):
                    event_types.append(fti.id)
    finally:
        # Delete the tmp_folder again
        tmp_folder.__parent__.manage_delObjects([tmp_folder_id])

    return SimpleVocabulary.fromValues(event_types)
    def test_fix_interface_for_event(self):
        self.obj.portal_type = 'Event'
        self.catalog.reindexObject(self.obj)

        self.portal.restrictedTraverse('fix_base_classes')()

        self.assertTrue(IEvent.providedBy(self.obj))
def EventTypes(context):
    """ Vocabulary for available event types.

    Insane stuff: All types are created temporary and checked if the provide
    the IEvent interface. At least, this function is cached forever the Zope
    process lives.
    """
    # TODO: I'd love to query the factory for types, who's instances are
    # implementing a specific interface via the portal_factory API.

    portal = getSite()
    tmp_folder_id = 'event_types_temp_folder__%s' % random.randint(0, 99999999)
    portal.invokeFactory('Folder', tmp_folder_id)
    try:
        tmp_folder = portal._getOb(tmp_folder_id)
        portal_types = getToolByName(portal, 'portal_types')
        all_types = portal_types.listTypeInfo(portal)
        event_types = []
        cnt = 0
        for fti in all_types:
            if not getattr(fti, 'global_allow', False):
                continue
            cnt += 1
            tmp_id = 'temporary__event_types__%s' % cnt
            tmp_obj = None
            fti.constructInstance(tmp_folder, tmp_id)
            tmp_obj = tmp_folder._getOb(tmp_id)
            if tmp_obj:
                if IEvent.providedBy(tmp_obj):
                    event_types.append(fti.id)
    finally:
        # Delete the tmp_folder again
        tmp_folder.__parent__.manage_delObjects([tmp_folder_id])

    return SimpleVocabulary.fromValues(event_types)
Beispiel #5
0
def timezone_handler(obj, event):
    """ When setting the startDate and endDate, the value of the timezone field
    isn't known, so we have to convert those timezone-naive dates into
    timezone-aware ones afterwards.

    """

    if not IEvent.providedBy(obj):
        # don't run me, if i'm not installed
        return

    timezone = obj.getField('timezone').get(obj)
    start_field = obj.getField('startDate')
    end_field = obj.getField('endDate')
    start = start_field.get(obj)
    end = end_field.get(obj)

    def make_DT(value, timezone):
        return DateTime(
            value.year(),
            value.month(),
            value.day(),
            value.hour(),
            value.minute(),
            value.second(),
            timezone)

    start = make_DT(start, timezone).toZone('UTC')
    end = make_DT(end, timezone).toZone('UTC')
    start_field.set(obj, start)
    end_field.set(obj, end)
    obj.reindexObject()
def ticket_title_generator(obj):
    """Generate a title for the ticket, also using event information.
    """

    event = obj
    ret = {
        'title': obj.title, 'eventtitle': '', 'eventstart': '', 'eventend': ''
    }

    if ITicketOccurrence.providedBy(event):
        event = aq_parent(aq_parent(event))
        # Traverse to the Occurrence object
        if IATEvent.providedBy(event):
            # get the request out of thin air to be able to publishTraverse to
            # the transient Occurrence object.
            traverser = OccTravAT(event, getRequest())
        elif IDXEvent.providedBy(event):
            # TODO
            traverser = OccTravDX(event, getRequest())
        else:
            raise NotImplementedError(
                u"There is no event occurrence traverser implementation for "
                u"this kind of object."
            )
        try:
            event = traverser.publishTraverse(getRequest(), obj.id)
        except KeyError:
            # Maybe the ticket occurrence isn't valid anymore because the
            # event occurence doesn't exist anymore.
            # Just ignore that case.
            return ret

    elif ITicket.providedBy(event):
        event = aq_parent(event)

    if IEvent.providedBy(event) or IOccurrence.providedBy(event):
        acc = IEventAccessor(event)
        lstart = ulocalized_time(
            DT(acc.start),
            long_format=True,
            context=event
        )
        lend = ulocalized_time(
            DT(acc.start),
            long_format=True,
            context=event
        )
        # XXX: no unicode, store as utf-8 encoded string instead
        ret = dict(
            title=u'%s - %s (%s - %s)' % (
                safe_unicode(acc.title),
                safe_unicode(obj.title),
                lstart,
                lend,
            ),
            eventtitle=acc.title,
            eventstart=acc.start,
            eventend=acc.end,
        )
    return ret
    def test_fix_interface_for_event(self):
        self.obj.portal_type = 'Event'
        self.catalog.reindexObject(self.obj)

        self.portal.restrictedTraverse('fix_base_classes')()

        self.assertTrue(IEvent.providedBy(self.obj))
 def set_allDay(self, v):
     v = bool(v)
     if HAS_PAE:
         if IEvent.providedBy(self.context):
             acc = IEventAccessor(self.context)
             acc.whole_day = v
             return
     self._all_day = v
Beispiel #9
0
 def _allDay(self):
     if HAS_PAE:
         if IEvent.providedBy(self.context):
             acc = IEventAccessor(self.context)
             return acc.whole_day or False
     if self._all_day is not None:
         return bool(self._all_day)
     return False
Beispiel #10
0
 def set_allDay(self, v):
     v = bool(v)
     if HAS_PAE:
         if IEvent.providedBy(self.context):
             acc = IEventAccessor(self.context)
             acc.whole_day = v
             return
     self._all_day = v
 def test_factory(self):
     fti = queryUtility(
         IDexterityFTI,
         name='Event'
     )
     factory = fti.factory
     new_object = createObject(factory)
     self.assertTrue(IEvent.providedBy(new_object))
Beispiel #12
0
    def test_upgrade_step_1(self):
        _dummy_1 = mkDummyInContext(MockATEvent_1, oid='dummy_1',
                                    context=self.portal,
                                    schema=ATContentTypeSchema)
        _dummy_1.title = 'Foo'
        _dummy_1.reindexObject()

        event = self.portal['dummy_1']
        self.assertTrue(not IEvent.providedBy(event))
        del event

        upgrade_step_1(self.portal)

        event = self.portal['dummy_1']
        self.assertTrue(IEvent.providedBy(event))
        self.assertEqual('', event.recurrence)
        self.assertEqual('Foo', event.Title())
 def _allDay(self):
     if HAS_PAE:
         if IEvent.providedBy(self.context):
             acc = IEventAccessor(self.context)
             return acc.whole_day or False
     if self._all_day is not None:
         return bool(self._all_day)
     return False
Beispiel #14
0
 def test_factory(self):
     fti = queryUtility(
         IDexterityFTI,
         name='Event'
     )
     factory = fti.factory
     new_object = createObject(factory)
     self.assertTrue(IEvent.providedBy(new_object))
Beispiel #15
0
def data_postprocessing(obj, event):
    """When setting the startDate and endDate, the value of the timezone field
    isn't known, so we have to convert those timezone-naive dates into
    timezone-aware ones afterwards.

    For whole day events, set start time to 0:00:00 and end time toZone
    23:59:59.

    """

    if not IEvent.providedBy(obj):
        # don't run me, if i'm not installed
        return

    timezone = obj.getField('timezone').get(obj)
    start_field = obj.getField('startDate')
    end_field = obj.getField('endDate')

    # The previous_timezone is set, when the timezone has changed to another
    # value. In this case we need to convert the UTC dt values to the
    # previous_timezone, so that we get the datetime values, as the user
    # entered them. However, this value might be always set, even when creating
    # an event, since ObjectModifiedEvent is called several times when editing.
    prev_tz = getattr(obj, 'previous_timezone', None)
    if prev_tz: delattr(obj, 'previous_timezone')

    def _fix_zone(dt, tz):
        if not dt.timezoneNaive():
            # The object is edited and the value alreadty stored in UTC on the
            # object. In this case we want the value converted to the given
            # timezone, in which the user entered the data.
            dt = dt.toZone(tz)
        return dt

    start = _fix_zone(start_field.get(obj), prev_tz and prev_tz or timezone)
    end = _fix_zone(end_field.get(obj), prev_tz and prev_tz or timezone)

    def make_DT(value, timezone):
        return DateTime(
            value.year(),
            value.month(),
            value.day(),
            value.hour(),
            value.minute(),
            value.second(),
            timezone)

    start = make_DT(start, timezone)
    end = make_DT(end, timezone)

    if obj.getWholeDay():
        start = DateTime('%s 0:00:00 %s' % (start.Date(), timezone))
        end = DateTime('%s 23:59:59 %s' % (end.Date(), timezone))

    start_field.set(obj, start.toZone('UTC'))
    end_field.set(obj, end.toZone('UTC'))
    obj.reindexObject()
Beispiel #16
0
    def test_upgrade_step_1(self):
        _dummy_1 = mkDummyInContext(MockATEvent_1,
                                    oid='dummy_1',
                                    context=self.portal,
                                    schema=ATContentTypeSchema)
        _dummy_1.title = 'Foo'
        _dummy_1.reindexObject()

        event = self.portal['dummy_1']
        self.assertTrue(not IEvent.providedBy(event))
        del event

        upgrade_step_1(self.portal)

        event = self.portal['dummy_1']
        self.assertTrue(IEvent.providedBy(event))
        self.assertEqual('', event.recurrence)
        self.assertEqual('Foo', event.Title())
Beispiel #17
0
def ticket_title_generator(obj):
    """Generate a title for the ticket, also using event information.
    """

    event = obj
    ret = {
        'title': obj.title,
        'eventtitle': '',
        'eventstart': '',
        'eventend': ''
    }

    if ITicketOccurrence.providedBy(event):
        event = aq_parent(aq_parent(event))
        # Traverse to the Occurrence object
        if IATEvent.providedBy(event):
            # get the request out of thin air to be able to publishTraverse to
            # the transient Occurrence object.
            traverser = OccTravAT(event, getRequest())
        elif IDXEvent.providedBy(event):
            # TODO
            traverser = OccTravDX(event, getRequest())
        else:
            raise NotImplementedError(
                u"There is no event occurrence traverser implementation for "
                u"this kind of object.")
        try:
            event = traverser.publishTraverse(getRequest(), obj.id)
        except KeyError:
            # Maybe the ticket occurrence isn't valid anymore because the
            # event occurence doesn't exist anymore.
            # Just ignore that case.
            return ret

    elif ITicket.providedBy(event):
        event = aq_parent(event)

    if IEvent.providedBy(event) or IOccurrence.providedBy(event):
        acc = IEventAccessor(event)
        lstart = ulocalized_time(DT(acc.start),
                                 long_format=True,
                                 context=event)
        lend = ulocalized_time(DT(acc.start), long_format=True, context=event)
        # XXX: no unicode, store as utf-8 encoded string instead
        ret = dict(
            title=u'%s - %s (%s - %s)' % (
                safe_unicode(acc.title),
                safe_unicode(obj.title),
                lstart,
                lend,
            ),
            eventtitle=acc.title,
            eventstart=acc.start,
            eventend=acc.end,
        )
    return ret
Beispiel #18
0
    def test_recurrence_occurrences(self):
        result = IRecurrenceSupport(self.data).occurrences()

        self.assertEqual(4, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
Beispiel #19
0
    def test_recurrence_occurrences(self):
        result = IRecurrenceSupport(self.data).occurrences()

        self.assertEqual(4, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
def _get_event_url(ticket):
    """Return the URL to an event or event occurrence for a ticket or ticket
    occurrence.
    """

    url = ticket.absolute_url()

    if ITicketOccurrence.providedBy(ticket):
        # assumption1: ticketoccurrence id = occurrence id
        # assumption2: ticketoccurrence parent = ticket
        event = aq_parent(aq_parent(ticket))
        if IEvent.providedBy(event):
            url = '{}/{}'.format(event.absolute_url(), ticket.id)

    elif ITicket.providedBy(ticket):
        event = aq_parent(ticket)
        if IEvent.providedBy(event):
            url = event.absolute_url()

    return url
    def test_implementsInterfaces(self):
        """Test if an ATEvent object implements all relevant interfaces.

        """
        self.assertTrue(IEvent.providedBy(self.obj))
        self.assertTrue(IEventRecurrence.providedBy(self.obj))
        self.assertTrue(IATEvent.providedBy(self.obj))
        self.assertTrue(IATEventRecurrence.providedBy(self.obj))

        self.assertTrue(IATEvent_ATCT.providedBy(self.obj))
        self.assertTrue(verifyObject(IATEvent_ATCT, self.obj))
def _get_event_url(ticket):
    """Return the URL to an event or event occurrence for a ticket or ticket
    occurrence.
    """

    url = ticket.absolute_url()

    if ITicketOccurrence.providedBy(ticket):
        # assumption1: ticketoccurrence id = occurrence id
        # assumption2: ticketoccurrence parent = ticket
        event = aq_parent(aq_parent(ticket))
        if IEvent.providedBy(event):
            url = "{}/{}".format(event.absolute_url(), ticket.id)

    elif ITicket.providedBy(ticket):
        event = aq_parent(ticket)
        if IEvent.providedBy(event):
            url = event.absolute_url()

    return url
Beispiel #23
0
def expand_events(events,
                  ret_mode,
                  start=None,
                  end=None,
                  sort=None,
                  sort_reverse=None):
    """Expand to the recurrence occurrences of a given set of events.

    :param events: IEvent based objects or IEventAccessor object wrapper.

    :param ret_mode: Return type of search results. These options are
                     available:

                         * 2 (objects): Return results as IEvent and/or
                                        IOccurrence objects.
                         * 3 (accessors): Return results as IEventAccessor
                                          wrapper objects.
                     Option "1" (brains) is not supported.

    :type ret_mode: integer [2|3]

    :param start: Date, from which on events should be expanded.
    :type start: Python datetime.

    :param end: Date, until which events should be expanded.
    :type end: Python datetime

    :param sort: Object or IEventAccessor Attribute to sort on.
    :type sort: string

    :param sort_reverse: Change the order of the sorting.
    :type sort_reverse: boolean
    """
    assert (ret_mode is not RET_MODE_BRAINS)

    exp_result = []
    for it in events:
        obj = it.getObject() if getattr(it, 'getObject', False) else it
        if IEventRecurrence.providedBy(obj):
            occurrences = [
                _obj_or_acc(occ, ret_mode)
                for occ in IRecurrenceSupport(obj).occurrences(start, end)
            ]
        elif IEvent.providedBy(obj):
            occurrences = [_obj_or_acc(obj, ret_mode)]
        else:
            # No IEvent based object. Could come from a collection.
            continue
        exp_result += occurrences
    if sort:
        exp_result.sort(key=lambda x: _get_compare_attr(x, sort))
    if sort_reverse:
        exp_result.reverse()
    return exp_result
Beispiel #24
0
    def test_recurrence_occurrences_with_range_start_1(self):
        # Test with range
        rs = datetime.datetime(2011, 11, 15, 11, 0, tzinfo=self.tz)
        result = IRecurrenceSupport(self.data).occurrences(range_start=rs)

        self.assertEqual(4, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
Beispiel #25
0
    def test_recurrence_occurrences_with_range_start_1(self):
        # Test with range
        rs = datetime.datetime(2011, 11, 15, 11, 0, tzinfo=self.tz)
        result = IRecurrenceSupport(self.data).occurrences(range_start=rs)

        self.assertEqual(4, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
    def filterOccurrenceEvents(self, events):
        filter_events = []
        for event in events:
            if not IEvent.providedBy(event):
                ocurrence = event
                event = event.aq_parent
                if event not in filter_events:
                    event.ocstart = ocurrence.start
                    event.ocend = ocurrence.end
                    filter_events.append(event)
            else:
                filter_events.append(event)

        return filter_events
Beispiel #27
0
def expand_events(events, ret_mode,
                  start=None, end=None,
                  sort=None, sort_reverse=None):
    """Expand to the recurrence occurrences of a given set of events.

    :param events: IEvent based objects or IEventAccessor object wrapper.

    :param ret_mode: Return type of search results. These options are
                     available:

                         * 2 (objects): Return results as IEvent and/or
                                        IOccurrence objects.
                         * 3 (accessors): Return results as IEventAccessor
                                          wrapper objects.
                     Option "1" (brains) is not supported.

    :type ret_mode: integer [2|3]

    :param start: Date, from which on events should be expanded.
    :type start: Python datetime.

    :param end: Date, until which events should be expanded.
    :type end: Python datetime

    :param sort: Object or IEventAccessor Attribute to sort on.
    :type sort: string

    :param sort_reverse: Change the order of the sorting.
    :type sort_reverse: boolean
    """
    assert(ret_mode is not RET_MODE_BRAINS)

    exp_result = []
    for it in events:
        obj = it.getObject() if getattr(it, 'getObject', False) else it
        if IEventRecurrence.providedBy(obj):
            occurrences = [_obj_or_acc(occ, ret_mode) for occ in
                           IRecurrenceSupport(obj).occurrences(start, end)]
        elif IEvent.providedBy(obj):
            occurrences = [_obj_or_acc(obj, ret_mode)]
        else:
            # No IEvent based object. Could come from a collection.
            continue
        exp_result += occurrences
    if sort:
        exp_result.sort(key=lambda x: _get_compare_attr(x, sort))
    if sort_reverse:
        exp_result.reverse()
    return exp_result
Beispiel #28
0
    def test_recurrence_occurrences_with_range_start_and_end(self):
        # Test with range
        rs = datetime.datetime(2011, 11, 11, 11, 0, tzinfo=self.tz)
        re = datetime.datetime(2011, 11, 12, 11, 0, tzinfo=self.tz)
        result = IRecurrenceSupport(self.data).occurrences(range_start=rs,
                                                           range_end=re)
        result = list(result)  # cast generator to list

        self.assertEqual(2, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
Beispiel #29
0
    def test_recurrence_occurrences_with_range_start_and_end(self):
        # Test with range
        rs = datetime.datetime(2011, 11, 11, 11, 0, tzinfo=self.tz)
        re = datetime.datetime(2011, 11, 12, 11, 0, tzinfo=self.tz)
        result = IRecurrenceSupport(self.data).occurrences(range_start=rs,
                                                           range_end=re)
        result = list(result)  # cast generator to list

        self.assertEqual(2, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
    def test_recurrence(self):
        tz = pytz.timezone('Europe/Vienna')
        duration = datetime.timedelta(days=4)
        data = MockEvent()
        data.start = datetime.datetime(2011, 11, 11, 11, 00, tzinfo=tz)
        data.end = data.start + duration
        data.recurrence = 'RRULE:FREQ=DAILY;COUNT=4'
        zope.interface.alsoProvides(data, IEvent, IEventRecurrence)
        result = IRecurrenceSupport(data).occurrences()

        self.assertEqual(4, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
    def test_recurrence(self):
        tz = pytz.timezone('Europe/Vienna')
        duration = datetime.timedelta(days=4)
        data = MockEvent()
        data.start = datetime.datetime(2011, 11, 11, 11, 00, tzinfo=tz)
        data.end = data.start + duration
        data.recurrence = 'RRULE:FREQ=DAILY;COUNT=4'
        zope.interface.alsoProvides(data, IEvent, IEventRecurrence)
        result = IRecurrenceSupport(data).occurrences()

        self.assertEqual(4, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
Beispiel #32
0
def whole_day_handler(obj, event):
    """ For whole day events only, set start time to 0:00:00 and end time to
        23:59:59
    """

    if not IEvent.providedBy(obj):
        # don't run me, if i'm not installed
        return

    if not obj.whole_day:
        return

    startDate = obj.startDate.toZone(obj.timezone)
    startDate = startDate.Date() + ' 0:00:00 ' + startDate.timezone()
    endDate = obj.endDate.toZone(obj.timezone)
    endDate = endDate.Date() + ' 23:59:59 ' + endDate.timezone()
    obj.setStartDate(DateTime(startDate)) # TODO: setting needed? aren't above operations operating on the instances itself?
    obj.setEndDate(DateTime(endDate))
    obj.reindexObject()  # reindex obj to store upd values in catalog
Beispiel #33
0
 def toLocalizedTime(self,
                     time=None,
                     long_format=None,
                     time_only=None,
                     event=None,
                     startend='start'):
     if event:
         if not IEvent.providedBy(event):
             event = event.getObject()
         rs = RecurrenceSupport(event)
         occurences = [occ for occ in rs.occurrences(datetime.today())]
         if len(occurences) >= 1:
             # do not get object which started in the past
             if startend == 'start':
                 time = getattr(occurences[0], 'start')
             elif startend == 'end':
                 time = getattr(occurences[-1], 'end')
     return self.context.restrictedTraverse('@@plone').toLocalizedTime(
         time, long_format, time_only)
Beispiel #34
0
    def test_recurrence(self):
        tz = pytz.timezone('Europe/Vienna')
        duration = timedelta(days=4)
        mock = MockEvent()
        mock.start = tz.localize(datetime(2011, 11, 11, 11, 0))
        mock.end = mock.start + duration
        mock.recurrence = 'RRULE:FREQ=DAILY;COUNT=4'
        zope.interface.alsoProvides(mock, IEvent, IEventBasic,
                                    IEventRecurrence, IDXEvent,
                                    IDXEventRecurrence)
        result = IRecurrenceSupport(mock).occurrences()
        result = list(result)  # cast generator to list

        self.assertEqual(4, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
    def test_recurrence(self):
        tz = pytz.timezone('Europe/Vienna')
        duration = timedelta(days=4)
        mock = MockEvent()
        mock.start = tz.localize(datetime(2011, 11, 11, 11, 0))
        mock.end = mock.start + duration
        mock.recurrence = 'RRULE:FREQ=DAILY;COUNT=4'
        zope.interface.alsoProvides(
            mock, IEvent, IEventBasic, IEventRecurrence,
            IDXEvent, IDXEventRecurrence)
        result = IRecurrenceSupport(mock).occurrences()
        result = list(result)  # cast generator to list

        self.assertEqual(4, len(result))

        # First occurrence is an IEvent object
        self.assertTrue(IEvent.providedBy(result[0]))

        # Subsequent ones are IOccurrence objects
        self.assertTrue(IOccurrence.providedBy(result[1]))
 def events(self, ret_mode=3, batch=True):
     res = []
     is_col = self.is_collection
     is_top = self.is_topic
     if is_col or is_top:
         ctx = self.default_context
         if is_col:
             res = ctx.results(batch=False, sort_on='start', brains=False)
         else:
             res = ctx.queryCatalog(
                 REQUEST=self.request, batch=False, full_objects=True
             )
         # TODO: uff, we have to walk through all results...
         if ret_mode == 3:
             res = [IEventAccessor(obj) for obj in res
                    if IEvent.providedBy(obj)]
     else:
         res = self._get_events(ret_mode)
     if batch:
         b_start = self.b_start
         b_size  = self.b_size
         res = Batch(res, size=b_size, start=b_start, orphan=self.orphan)
     return res
Beispiel #37
0
 def events(self, ret_mode=3, batch=True):
     res = []
     is_col = self.is_collection
     is_top = self.is_topic
     if is_col or is_top:
         ctx = self.default_context
         if is_col:
             res = ctx.results(batch=False, sort_on='start', brains=False)
         else:
             res = ctx.queryCatalog(
                 REQUEST=self.request, batch=False, full_objects=True
             )
         # TODO: uff, we have to walk through all results...
         if ret_mode == 3:
             res = [IEventAccessor(obj) for obj in res
                    if IEvent.providedBy(obj)]
     else:
         res = self._get_events(ret_mode)
     if batch:
         b_start = self.b_start
         b_size  = self.b_size
         res = Batch(res, size=b_size, start=b_start, orphan=self.orphan)
     return res
    def dict_from_item(item):
        if hasPloneAppEvent and (IEvent.providedBy(item) or IOccurrence.providedBy(item)):
            is_occurrence = IOccurrence.providedBy(item) and True or False
            acc = IEventAccessor(item)
            return {
                "status": "ok",
                "id": "UID_%s" % (acc.uid),
                "title": acc.title,
                "description": acc.description,
                "start": acc.start.isoformat(),
                "end": acc.end.isoformat(),
                "url": acc.url,
                "editable": editable,
                "allDay": acc.whole_day,
                "className": "contextualContentMenuEnabled %s %s %s %s"
                % (
                    state and "state-%s" % str(state) or "",
                    editable and "editable" or "",
                    css and css or "",
                    is_occurrence and "occurrence" or "",
                ),
                "color": color,
            }
        elif IATEvent.providedBy(item):

            allday = (item.end() - item.start()) > 1.0
            adapted = interfaces.ISFBaseEventFields(item, None)
            if adapted:
                allday = adapted.allDay

            return [
                {
                    "status": "ok",
                    "id": "UID_%s" % (item.UID()),
                    "title": item.Title(),
                    "description": item.Description(),
                    "start": item.start().rfc822(),
                    "end": item.end().rfc822(),
                    "url": item.absolute_url(),
                    "editable": editable,
                    "allDay": allday,
                    "className": "contextualContentMenuEnabled %s %s %s"
                    % (state and "state-%s" % str(state) or "", editable and "editable" or "", css and css or ""),
                    "color": color,
                }
            ]
        elif ICatalogBrain.providedBy(item):
            if type(item.end) != DateTime:
                brainend = DateTime(item.end)
                brainstart = DateTime(item.start)
            else:
                brainend = item.end
                brainstart = item.start

            allday = (brainend - brainstart) > 1.0

            if getattr(item, "SFAllDay", None) in [False, True]:
                allday = item.SFAllDay

            return [
                {
                    "status": "ok",
                    "id": "UID_%s" % (item.UID),
                    "title": item.Title,
                    "description": item.Description,
                    "start": brainstart.rfc822(),
                    "end": brainend.rfc822(),
                    "url": item.getURL(),
                    "editable": editable,
                    "allDay": allday,
                    "className": "contextualContentMenuEnabled %s %s %s"
                    % (state and "state-%s" % str(state) or "", editable and "editable" or "", css and css or ""),
                    "color": color,
                }
            ]
        else:
            raise ValueError("item type not supported for: %s" % repr(item))
Beispiel #39
0
    def dict_from_item(item):
        if hasPloneAppEvent and (IEvent.providedBy(item) or
                                 IOccurrence.providedBy(item)):
            # plone.app.event DX or AT Event
            is_occurrence = IOccurrence.providedBy(item)
            acc = IEventAccessor(item)

            return {
                "status": "ok",
                "id": "UID_%s" % (acc.uid),
                "title": acc.title,
                "description": acc.description,
                "start": acc.start.isoformat(),
                "end": acc.end.isoformat(),
                "url": acc.url,
                "editable": editable,
                "allDay": acc.whole_day,
                "className": "contextualContentMenuEnabled %s %s %s %s" % (
                                state and "state-%s" % str(state) or "",
                                editable and "editable" or "",
                                css and css or "",
                                is_occurrence and "occurrence" or ""),
                "color": color}
        elif IATEvent.providedBy(item):
            # Products.ATContentTypes ATEvent
            allday = (item.end() - item.start()) > 1.0
            adapted = interfaces.ISFBaseEventFields(item, None)
            if adapted:
                allday = adapted.allDay
            return {
                "status": "ok",
                "id": "UID_%s" % (item.UID()),
                "title": item.Title(),
                "description": item.Description(),
                "start": item.start().ISO8601(),
                "end": item.end().ISO8601(),
                "url": item.absolute_url(),
                "editable": editable,
                "allDay": allday,
                "className": "contextualContentMenuEnabled %s %s %s" % (
                                state and "state-%s" % str(state) or "",
                                editable and "editable" or "",
                                css and css or ""),
                "color": color}
        elif ICatalogBrain.providedBy(item):
            # Event catalog brain
            if type(item.end) != DateTime:
                brainend = DateTime(item.end)
                brainstart = DateTime(item.start)
            else:
                brainend = item.end
                brainstart = item.start

            allday = (brainend - brainstart) > 1.0

            if getattr(item, 'SFAllDay', None) in [False, True]:
                allday = item.SFAllDay

            # Set Mexico City Time
            brainstart = DateTime(' '.join(
                (brainstart.Date(), brainstart.Time(), 'America/Mexico_City')))
            brainend = DateTime(' '.join(
                (brainend.Date(), brainend.Time(), 'America/Mexico_City')))

            return {
                "status": "ok",
                "id": "UID_%s" % (item.UID),
                "title": item.Title,
                "description": item.Description,
                "start": brainstart.ISO8601(),
                "end": brainend.ISO8601(),
                "url": item.getURL(),
                "editable": editable,
                "allDay": allday,
                "className": "contextualContentMenuEnabled %s %s %s" % (
                                state and "state-%s" % str(state) or "",
                                editable and "editable" or "",
                                css and css or ""),
                "color": color}
        else:
            raise ValueError('item type not supported for: %s' % repr(item))
Beispiel #40
0
    def isEvent(self, item):

        if getattr(item, 'getObject', False):
            item = item.getObject()

        return IEvent.providedBy(item)
Beispiel #41
0
def construct_icalendar(context, events):
    """Returns an icalendar.Calendar object.

    :param context: A content object, which is used for calendar details like
                    Title and Description. Usually a container, collection or
                    the event itself.

    :param events: The list of event objects, which are included in this
                   calendar.
    """
    cal = icalendar.Calendar()
    cal.add('prodid', PRODID)
    cal.add('version', VERSION)

    cal_tz = default_timezone(context)
    if cal_tz:
        cal.add('x-wr-timezone', cal_tz)

    tzmap = {}
    if not getattr(events, '__getitem__', False):
        events = [events]
    for event in events:
        if ICatalogBrain.providedBy(event) or\
                IContentListingObject.providedBy(event):
            event = event.getObject()
        if not (IEvent.providedBy(event) or IOccurrence.providedBy(event)):
            # Must be an event.
            continue
        acc = IEventAccessor(event)
        tz = acc.timezone
        # TODO: the standard wants each recurrence to have a valid timezone
        # definition. sounds decent, but not realizable.
        if not acc.whole_day:  # whole day events are exported as dates without
            # timezone information
            if isinstance(tz, tuple):
                tz_start, tz_end = tz
            else:
                tz_start = tz_end = tz
            tzmap = add_to_zones_map(tzmap, tz_start, acc.start)
            tzmap = add_to_zones_map(tzmap, tz_end, acc.end)
        cal.add_component(IICalendarEventComponent(event).to_ical())

    for (tzid, transitions) in tzmap.items():
        cal_tz = icalendar.Timezone()
        cal_tz.add('tzid', tzid)
        cal_tz.add('x-lic-location', tzid)

        for (transition, tzinfo) in transitions.items():

            if tzinfo['dst']:
                cal_tz_sub = icalendar.TimezoneDaylight()
            else:
                cal_tz_sub = icalendar.TimezoneStandard()

            cal_tz_sub.add('tzname', tzinfo['name'])
            cal_tz_sub.add('dtstart', transition)
            cal_tz_sub.add('tzoffsetfrom', tzinfo['tzoffsetfrom'])
            cal_tz_sub.add('tzoffsetto', tzinfo['tzoffsetto'])
            # TODO: add rrule
            # tzi.add('rrule',
            #         {'freq': 'yearly', 'bymonth': 10, 'byday': '-1su'})
            cal_tz.add_component(cal_tz_sub)
        cal.add_component(cal_tz)

    return cal
Beispiel #42
0
    def test_get_events(self):

        # whole range
        res = get_events(self.portal)
        self.assertEqual(len(res), 4)

        res = get_events(self.portal,
                         start=self.past,
                         end=self.future)
        self.assertEqual(len(res), 4)

        res = get_events(self.portal,
                         end=self.future)
        self.assertEqual(len(res), 4)

        res = get_events(self.portal,
                         start=self.past)
        self.assertEqual(len(res), 4)

        # Limit
        res = get_events(self.portal, limit=2)
        self.assertEqual(len(res), 2)

        # Return objects
        res = get_events(self.portal, ret_mode=RET_MODE_OBJECTS)
        self.assertTrue(IEvent.providedBy(res[0]))

        # Return IEventAccessor
        res = get_events(self.portal, ret_mode=RET_MODE_ACCESSORS)
        self.assertTrue(IEventAccessor.providedBy(res[0]))
        # Test sorting
        self.assertTrue(res[0].start < res[-1].start)

        # Test reversed sorting
        res = get_events(self.portal, ret_mode=RET_MODE_ACCESSORS,
                         sort_reverse=True)
        self.assertTrue(res[0].start > res[-1].start)

        # Test sort_on
        res = get_events(self.portal, ret_mode=RET_MODE_ACCESSORS,
                         sort="start")
        self.assertEqual(
            [it.title for it in res][2:],
            [u'Now Event', u'Future Event']
        )
        res = get_events(self.portal, ret_mode=RET_MODE_ACCESSORS, sort="end")
        self.assertEqual(
            [it.title for it in res],
            [u'Past Event', u'Now Event', u'Future Event', u'Long Event']
        )

        # Test expansion
        res = get_events(self.portal, ret_mode=RET_MODE_OBJECTS, expand=True)
        self.assertEqual(len(res), 8)

        res = get_events(self.portal, ret_mode=RET_MODE_ACCESSORS, expand=True)
        self.assertEqual(len(res), 8)
        # Test sorting
        self.assertTrue(res[0].start < res[-1].start)

        res = get_events(self.portal, ret_mode=RET_MODE_ACCESSORS,
                         expand=True, sort_reverse=True)
        # Test sorting
        self.assertTrue(res[0].start > res[-1].start)

        # only on now-date
        res = get_events(self.portal,
                         start=self.now,
                         end=self.now)
        self.assertEqual(len(res), 2)

        # only on now-date as date
        # NOTE: converting self.now to python datetime to allow testing also
        # with dates as Zope DateTime objects.
        res = get_events(self.portal,
                         start=pydt(self.now).date(),
                         end=pydt(self.now).date())
        self.assertEqual(len(res), 2)

        # only on past date
        res = get_events(self.portal,
                         start=self.past,
                         end=self.past)
        self.assertEqual(len(res), 2)

        # one recurrence occurrence in far future
        res = get_events(self.portal,
                         start=self.far,
                         end=self.far)
        self.assertEqual(len(res), 1)

        # from now on
        res = get_events(self.portal,
                         start=self.now)
        self.assertEqual(len(res), 3)

        # until now
        res = get_events(self.portal,
                         end=self.now)
        self.assertEqual(len(res), 3)

        # in subfolder
        path = '/'.join(self.portal.sub.getPhysicalPath())
        res = get_events(self.portal, path=path)
        self.assertEqual(len(res), 1)
Beispiel #43
0
 def is_event_collection(self, brains):
     if len(brains) > 0:
         obj = brains[0].getObject()
         return IEvent.providedBy(obj)
     return False
 def test_adding(self):
     self.portal.invokeFactory(
         'Event',
         'doc1'
     )
     self.assertTrue(IEvent.providedBy(self.portal['doc1']))
Beispiel #45
0
 def test_adding(self):
     self.portal.invokeFactory(
         'Event',
         'doc1'
     )
     self.assertTrue(IEvent.providedBy(self.portal['doc1']))
Beispiel #46
0
 def map_link(self):
     if IEvent.providedBy(self.context):
         return getattr(self.context, 'map_link', None)
Beispiel #47
0
    def dict_from_item(item):
        if hasPloneAppEvent and (IEvent.providedBy(item) or
                                 IOccurrence.providedBy(item)):
            # plone.app.event DX or AT Event
            is_occurrence = IOccurrence.providedBy(item)
            acc = IEventAccessor(item)
            return {
                "status": "ok",
                "id": "UID_%s" % (acc.uid),
                "title": acc.title,
                "description": acc.description,
                "start": acc.start.isoformat(),
                "end": acc.end.isoformat(),
                "url": acc.url,
                "editable": editable,
                "allDay": acc.whole_day,
                "className": "contextualContentMenuEnabled %s %s %s %s" % (
                                state and "state-%s" % str(state) or "",
                                editable and "editable" or "",
                                css and css or "",
                                is_occurrence and "occurrence" or ""),
                "color": color}
        elif IATEvent.providedBy(item):
            # Products.ATContentTypes ATEvent
            allday = (item.end() - item.start()) > 1.0
            adapted = interfaces.ISFBaseEventFields(item, None)
            if adapted:
                allday = adapted.allDay

            return {
                "status": "ok",
                "id": "UID_%s" % (item.UID()),
                "title": item.Title(),
                "description": item.Description(),
                "start": item.start().ISO8601(),
                "end": item.end().ISO8601(),
                "url": item.absolute_url(),
                "editable": editable,
                "allDay": allday,
                "className": "contextualContentMenuEnabled %s %s %s" % (
                                state and "state-%s" % str(state) or "",
                                editable and "editable" or "",
                                css and css or ""),
                "color": color}
        elif ICatalogBrain.providedBy(item):
            # Event catalog brain
            if type(item.end) != DateTime:
                brainend = DateTime(item.end)
                brainstart = DateTime(item.start)
            else:
                brainend = item.end
                brainstart = item.start

            allday = (brainend - brainstart) > 1.0

            if getattr(item, 'SFAllDay', None) in [False, True]:
                allday = item.SFAllDay

            return {
                "status": "ok",
                "id": "UID_%s" % (item.UID),
                "title": item.Title,
                "description": item.Description,
                "start": brainstart.ISO8601(),
                "end": brainend.ISO8601(),
                "url": item.getURL(),
                "editable": editable,
                "allDay": allday,
                "className": "contextualContentMenuEnabled %s %s %s" % (
                                state and "state-%s" % str(state) or "",
                                editable and "editable" or "",
                                css and css or ""),
                "color": color}
        else:
            raise ValueError('item type not supported for: %s' % repr(item))
Beispiel #48
0
def construct_icalendar(context, events):
    """Returns an icalendar.Calendar object.

    :param context: A content object, which is used for calendar details like
                    Title and Description. Usually a container, collection or
                    the event itself.

    :param events: The list of event objects, which are included in this
                   calendar.
    """
    cal = icalendar.Calendar()
    cal.add('prodid', PRODID)
    cal.add('version', VERSION)

    cal_tz = default_timezone(context)
    if cal_tz:
        cal.add('x-wr-timezone', cal_tz)

    tzmap = {}
    if not getattr(events, '__getitem__', False):
        events = [events]
    for event in events:
        if ICatalogBrain.providedBy(event) or\
                IContentListingObject.providedBy(event):
            event = event.getObject()
        if not (IEvent.providedBy(event) or IOccurrence.providedBy(event)):
            # Must be an event.
            continue
        acc = IEventAccessor(event)
        tz = acc.timezone
        # TODO: the standard wants each recurrence to have a valid timezone
        # definition. sounds decent, but not realizable.
        if not acc.whole_day:  # whole day events are exported as dates without
                               # timezone information
            if isinstance(tz, tuple):
                tz_start, tz_end = tz
            else:
                tz_start = tz_end = tz
            tzmap = add_to_zones_map(tzmap, tz_start, acc.start)
            tzmap = add_to_zones_map(tzmap, tz_end, acc.end)
        cal.add_component(IICalendarEventComponent(event).to_ical())

    for (tzid, transitions) in tzmap.items():
        cal_tz = icalendar.Timezone()
        cal_tz.add('tzid', tzid)
        cal_tz.add('x-lic-location', tzid)

        for (transition, tzinfo) in transitions.items():

            if tzinfo['dst']:
                cal_tz_sub = icalendar.TimezoneDaylight()
            else:
                cal_tz_sub = icalendar.TimezoneStandard()

            cal_tz_sub.add('tzname', tzinfo['name'])
            cal_tz_sub.add('dtstart', transition)
            cal_tz_sub.add('tzoffsetfrom', tzinfo['tzoffsetfrom'])
            cal_tz_sub.add('tzoffsetto', tzinfo['tzoffsetto'])
            # TODO: add rrule
            # tzi.add('rrule',
            #         {'freq': 'yearly', 'bymonth': 10, 'byday': '-1su'})
            cal_tz.add_component(cal_tz_sub)
        cal.add_component(cal_tz)

    return cal
Beispiel #49
0
    def data(self):

        context = self.context

        data = {}

        if ICollegeHomepage.providedBy(self.context):
            data = {
                    '@context': 'http://schema.org',
                    '@type': 'EducationalOrganization',
                    'address': {    '@type': 'PostalAddress',
                                    'addressLocality': 'University Park',
                                    'addressRegion': 'PA',
                                    'postalCode': '16802',
                                    'streetAddress': 'Penn State University'},
                    'logo': 'https://agsci.psu.edu/psu-agsciences-logo.png',
                    'name': 'Penn State College of Agricultural Sciences',
                    'sameAs': [
                        'https://www.facebook.com/agsciences',
                        'https://www.twitter.com/agsciences',
                        'https://plus.google.com/+PennStateAgSciences',
                        'https://instagram.com/agsciences',
                        'https://www.linkedin.com/company/penn-state-college-of-agricultural-sciences',
                        'https://www.youtube.com/psuagsciences',
                        'https://en.wikipedia.org/wiki/Penn_State_College_of_Agricultural_Sciences'],
                    'telephone': '+1-814-865-7521',
                    'url': 'https://agsci.psu.edu'
                    }

        elif IEvent.providedBy(context):

            data = {
                    '@context': 'http://schema.org',
                    '@type': 'Event',
                    'name': context.Title(),
                    'description' : context.Description(),
                    'startDate' : localize(context.start).isoformat(),
                    'endDate' : localize(context.end).isoformat(),
                    'url' : context.absolute_url(),
                    'location' : {
                        "@type" : "Place",
                        "address" : getattr(context, 'location', ''),
                        "name" : getattr(context, 'location', ''),
                    }
            }

        elif INewsItem.providedBy(context):

            data = {
                    '@context': 'http://schema.org',
                    '@type': 'Article',
                    'headline': context.Title(),
                    'description' : context.Description(),
                    'datePublished' : localize(context.effective()).isoformat(),
                    'url' : context.absolute_url(),
            }

        elif IPerson.providedBy(context):

            # Job Title
            job_titles = getattr(context, 'job_titles', [])

            if job_titles:
                job_title = job_titles[0]
            else:
                job_title = ""

            # Email
            email = getattr(context, 'email', '')

            # Name
            (first_name, middle_name, last_name) = [getattr(context, x, '') for x in ('first_name', 'middle_name', 'last_name')]

            # Address
            street_address = getattr(context, 'street_address', [])

            if street_address:
                street_address = [x for x in street_address if x]
                street_address = ', '.join(street_address)

            city = getattr(context, 'city', '')
            state = getattr(context, 'state', '')
            zip_code = getattr(context, 'zip_code', '')

            # Phone
            phone_number = getattr(context, 'phone_number', '')

            data = {
                    '@context': 'http://schema.org',
                    '@type': 'Person',
                    'url' : context.absolute_url(),
                    'email' : email,
                    'givenName' : first_name,
                    'additionalName' : middle_name,
                    'familyName' : last_name,
                    'telephone' : phone_number,
                    'jobTitle' : job_title,
                    'workLocation' : {
                        '@type' : 'PostalAddress',
                        'addressCountry' : 'US',
                        'addressLocality' : city,
                        'addressRegion' : state,
                        'postalCode' : zip_code,
                        'streetAddress' : street_address,
                    }
            }

        data['image'] = self.image

        if data:
            return json.dumps(data, indent=4)
Beispiel #50
0
 def test_upgrade_step_1(self):
     upgrade_step_1(self.portal)
     event = self.portal["dummy_1"]
     self.assertTrue(IEvent.providedBy(event))
     self.assertEqual("", event.recurrence)
     self.assertEqual("Foo", event.Title())
Beispiel #51
0
def data_postprocessing(obj, event):
    """When setting the startDate and endDate, the value of the timezone field
    isn't known, so we have to convert those timezone-naive dates into
    timezone-aware ones afterwards.

    For whole day events, set start time to 0:00:00 and end time to 23:59:59.
    For open end events, set end time to 23:59:59.
    """

    if not IEvent.providedBy(obj):
        # don't run me, if i'm not installed
        return

    timezone = obj.getField('timezone').get(obj)
    start_field = obj.getField('startDate')
    end_field = obj.getField('endDate')

    # The previous_timezone is set, when the timezone has changed to another
    # value. In this case we need to convert the UTC dt values to the
    # previous_timezone, so that we get the datetime values, as the user
    # entered them. However, this value might be always set, even when creating
    # an event, since ObjectModifiedEvent is called several times when editing.
    prev_tz = getattr(obj, 'previous_timezone', None)
    if prev_tz:
        delattr(obj, 'previous_timezone')

    def _fix_zone(dt, tz):
        if not dt.timezoneNaive():
            # The object is edited and the value alreadty stored in UTC on the
            # object. In this case we want the value converted to the given
            # timezone, in which the user entered the data.
            dt = dt.toZone(tz)
        return dt

    start = _fix_zone(start_field.get(obj), prev_tz and prev_tz or timezone)
    end = _fix_zone(end_field.get(obj), prev_tz and prev_tz or timezone)

    def make_DT(value, timezone):
        return DateTime(
            value.year(),
            value.month(),
            value.day(),
            value.hour(),
            value.minute(),
            int(value.second()),  # No microseconds
            timezone)

    start = make_DT(start, timezone)
    end = make_DT(end, timezone)

    whole_day = obj.getWholeDay()
    open_end = obj.getOpenEnd()
    if whole_day:
        start = DateTime('%s 0:00:00 %s' % (start.Date(), timezone))
    if open_end:
        end = start  # Open end events end on same day
    if open_end or whole_day:
        end = DateTime('%s 23:59:59 %s' % (end.Date(), timezone))

    start_field.set(obj, start.toZone('UTC'))
    end_field.set(obj, end.toZone('UTC'))

    if not obj.getEventUid():
        # sync_uid has to be set for icalendar data exchange.
        uid = IUUID(obj)
        # We don't want to fail when getRequest() returns None, e.g when
        # creating an event during test layer setup time.
        request = getRequest() or {}
        domain = request.get('HTTP_HOST')
        obj.setEventUid('%s%s' % (
            uid,
            domain and '@%s' % domain or ''
        ))

    obj.reindexObject()
Beispiel #52
0
 def is_event(self, obj):
     if getattr(obj, 'getObject', False):
         obj = obj.getObject()
     return IEvent.providedBy(obj)
Beispiel #53
0
 def is_event(self, obj):
     if getattr(obj, 'getObject', False):
         obj = obj.getObject()
     return IEvent.providedBy(obj)
Beispiel #54
0
def data_postprocessing(obj, event):
    """When setting the startDate and endDate, the value of the timezone field
    isn't known, so we have to convert those timezone-naive dates into
    timezone-aware ones afterwards.

    For whole day events, set start time to 0:00:00 and end time to 23:59:59.
    For open end events, set end time to 23:59:59.
    """

    if not IEvent.providedBy(obj):
        # don't run me, if i'm not installed
        return

    timezone = obj.getField('timezone').get(obj)
    start_field = obj.getField('startDate')
    end_field = obj.getField('endDate')

    # The previous_timezone is set, when the timezone has changed to another
    # value. In this case we need to convert the UTC dt values to the
    # previous_timezone, so that we get the datetime values, as the user
    # entered them. However, this value might be always set, even when creating
    # an event, since ObjectModifiedEvent is called several times when editing.
    prev_tz = getattr(obj, 'previous_timezone', None)
    if prev_tz:
        delattr(obj, 'previous_timezone')

    def _fix_zone(dt, tz):
        if not dt.timezoneNaive():
            # The object is edited and the value alreadty stored in UTC on the
            # object. In this case we want the value converted to the given
            # timezone, in which the user entered the data.
            dt = dt.toZone(tz)
        return dt

    start = _fix_zone(start_field.get(obj), prev_tz and prev_tz or timezone)
    end = _fix_zone(end_field.get(obj), prev_tz and prev_tz or timezone)

    def make_DT(value, timezone):
        return DateTime(
            value.year(),
            value.month(),
            value.day(),
            value.hour(),
            value.minute(),
            int(value.second()),  # No microseconds
            timezone)

    start = make_DT(start, timezone)
    end = make_DT(end, timezone)

    whole_day = obj.getWholeDay()
    open_end = obj.getOpenEnd()
    if whole_day:
        start = DateTime('%s 0:00:00 %s' % (start.Date(), timezone))
    if open_end:
        end = start  # Open end events end on same day
    if open_end or whole_day:
        end = DateTime('%s 23:59:59 %s' % (end.Date(), timezone))

    start_field.set(obj, start.toZone('UTC'))
    end_field.set(obj, end.toZone('UTC'))

    if not obj.getEventUid():
        # sync_uid has to be set for icalendar data exchange.
        uid = IUUID(obj)
        # We don't want to fail when getRequest() returns None, e.g when
        # creating an event during test layer setup time.
        request = getRequest() or {}
        domain = request.get('HTTP_HOST')
        obj.setEventUid('%s%s' % (uid, domain and '@%s' % domain or ''))

    obj.reindexObject()
Beispiel #55
0
 def __call__(self, *args, **kwargs):
     if not self._loaded:
         self._load_state()
     recipient = kwargs.get('recipient', None)
     if not IMailRecipient.providedBy(recipient):
         recipient = self._recipient_from_request()
     message = MIMEMultipart()
     self._set_headers(message, recipient)
     if HAS_PAE and IEvent.providedBy(self.context):
         accessor = IEventAccessor(self.context)
         timezone = accessor.timezone
         if not timezone:
             timezone = pytz.UTC
         timezone = pytz.timezone(timezone)
         start = accessor.start.astimezone(timezone)  # localtime of event
     else:
         start = self.context.start()
     data = {
         'FROM_NAME' : self.sender.reply_name,
         'FROM_EMAIL' : self.sender.reply_address,
         'DATE_FORMATTED' : self.timefn(
             start,
             context=aq_inner(self.context),
             request=self.request,
             ),
         'TIME_FORMATTED' : self.timefn(
             start,
             time_only=True,
             context=aq_inner(self.context),
             request=self.request,
             ),
         'ITEM_TITLE' : self.context.Title(),
         'ITEM_DESCRIPTION' : self.context.Description(),
         'ITEM_URL' : self.context.absolute_url(),
         'RSVP_URL' : self._rsvp_url(),
         'ATTACH_FMT' : 'A vCal',
         }
     if HAS_PAE and IEvent.providedBy(self.context):
         data['ATTACH_FMT'] = 'An iCalendar (.ics)'
         data['TIME_FORMATTED'] += ' (%s / %s)' % (
             start.tzinfo.tzname(start),
             utc_offset_label(start),
             )
     body = INVITE_EMAIL_BODY % data
     message.attach(MIMEText(body))
     if HAS_PAE and IEvent.providedBy(self.context):
         attachment = MIMEBase('text', 'calendar')
         attachment.set_payload(self._ical()) #data
         encoders.encode_base64(attachment)
         attachment.add_header('Content-Disposition',
                               'attachment',
                               filename='event.ics')
     else:
         attachment = MIMEBase('text', 'x-vCalendar')
         attachment.set_payload(self._vcal()) #data
         encoders.encode_base64(attachment)
         attachment.add_header('Content-Disposition',
                               'attachment',
                               filename='event.vcs')
     message.attach(attachment)
     return message.as_string()