265 lines
10 KiB
Python
265 lines
10 KiB
Python
from time import localtime
|
|
|
|
from Acquisition import aq_inner
|
|
from DateTime import DateTime
|
|
from zope.component import getMultiAdapter
|
|
from zope.i18nmessageid import MessageFactory
|
|
from Products.CMFPlone.utils import safe_unicode
|
|
|
|
from Products.CMFCore.utils import getToolByName
|
|
|
|
PLMF = MessageFactory('plonelocales')
|
|
|
|
class MonthlyView:
|
|
updated = False
|
|
|
|
def __init__(self, context, init_calendar=False):
|
|
self.context = context
|
|
self.updated = False
|
|
if init_calendar:
|
|
self.calendar = getToolByName(context, 'portal_calendar')
|
|
|
|
def update(self):
|
|
if self.updated:
|
|
return
|
|
self.updated = True
|
|
|
|
context = aq_inner(self.context)
|
|
self.calendar = getToolByName(context, 'portal_calendar')
|
|
self._ts = getToolByName(context, 'translation_service')
|
|
|
|
self.now = localtime()
|
|
self.yearmonth = yearmonth = self.getYearAndMonthToDisplay()
|
|
self.year = year = yearmonth[0]
|
|
self.month = month = yearmonth[1]
|
|
|
|
self.showPrevMonth = yearmonth > (self.now[0]-1, self.now[1])
|
|
self.showNextMonth = yearmonth < (self.now[0]+1, self.now[1])
|
|
|
|
self.prevMonthYear, self.prevMonthMonth = self.getPreviousMonth(year, month)
|
|
self.nextMonthYear, self.nextMonthMonth = self.getNextMonth(year, month)
|
|
|
|
self.monthName = PLMF(self._ts.month_msgid(month),
|
|
default=self._ts.month_english(month))
|
|
|
|
def get_events_from_catalog(self, start, end, portal_type=None, **keywords):
|
|
if portal_type is None:
|
|
portal_type = ('tabellio.agenda.event',
|
|
'tabellio.agenda.parlevent',
|
|
'tabellio.agenda.comevent')
|
|
|
|
catalog = getToolByName(self.context, 'portal_catalog')
|
|
|
|
def cmp_event(x, y):
|
|
if x.start == y.start:
|
|
return cmp(x.id, y.id)
|
|
return cmp(x.start, y.start)
|
|
|
|
rs = []
|
|
rsid = []
|
|
for brain in catalog(portal_type=portal_type,
|
|
review_state=self.calendar.getCalendarStates(),
|
|
start={'query': start, 'range': 'max'},
|
|
end={'query': end, 'range': 'min'},
|
|
**keywords) + \
|
|
catalog(portal_type=portal_type,
|
|
review_state=self.calendar.getCalendarStates(),
|
|
start={'query': (start, end), 'range': 'min:max'},
|
|
**keywords):
|
|
if type(brain.getId) is str:
|
|
if not brain.getId in rsid:
|
|
rs.append(brain)
|
|
rsid.append(brain.getId)
|
|
else:
|
|
if not brain.getId() in rsid:
|
|
rs.append(brain)
|
|
rsid.append(brain.getId())
|
|
return sorted(rs, cmp_event)
|
|
|
|
def catalog_getevents(self, year, month):
|
|
last_day = self.calendar._getCalendar().monthrange(year, month)[1]
|
|
first_date = self.calendar.getBeginAndEndTimes(1, month, year)[0]
|
|
last_date = self.calendar.getBeginAndEndTimes(last_day, month, year)[1]
|
|
|
|
query = self.get_events_from_catalog(last_date, first_date, sort_on='start')
|
|
# compile a list of the days that have events
|
|
eventDays={}
|
|
for daynumber in range(1, 32): # 1 to 31
|
|
eventDays[daynumber] = {'eventslist': [],
|
|
'event': 0,
|
|
'day': daynumber}
|
|
includedevents = []
|
|
for result in query:
|
|
result.end = DateTime(result.end)
|
|
result.start = DateTime(result.start)
|
|
if result.getRID() in includedevents:
|
|
break
|
|
else:
|
|
includedevents.append(result.getRID())
|
|
event={}
|
|
# we need to deal with events that end next month
|
|
if result.end.greaterThan(last_date):
|
|
eventEndDay = last_day
|
|
event['end'] = None
|
|
else:
|
|
eventEndDay = result.end.day()
|
|
if result.end == result.end.earliestTime():
|
|
event['end'] = (result.end - 1).latestTime().Time()
|
|
else:
|
|
event['end'] = result.end.Time()
|
|
# and events that started last month
|
|
if result.start.lessThan(first_date):
|
|
eventStartDay = 1
|
|
event['start'] = None
|
|
else:
|
|
eventStartDay = result.start.day()
|
|
event['start'] = result.start.Time()
|
|
|
|
event['title'] = result.Title or result.getId
|
|
event['type'] = result.portal_type.split('.')[-1]
|
|
event['id'] = result.getId
|
|
|
|
if eventStartDay != eventEndDay:
|
|
allEventDays = range(eventStartDay, eventEndDay+1)
|
|
eventDays[eventStartDay]['eventslist'].append(
|
|
{'end': None,
|
|
'start': result.start.Time(),
|
|
'title': event['title'],
|
|
'type': event['type'],
|
|
'id': event['id']} )
|
|
eventDays[eventStartDay]['event'] = 1
|
|
|
|
for eventday in allEventDays[1:-1]:
|
|
eventDays[eventday]['eventslist'].append(
|
|
{'end': None,
|
|
'start': None,
|
|
'title': event['title'],
|
|
'type': event['type'],
|
|
'id': event['id']} )
|
|
eventDays[eventday]['event'] = 1
|
|
|
|
if (result.end == result.end.earliestTime() and
|
|
event['end'] is not None):
|
|
# ends some day this month at midnight
|
|
last_day_data = eventDays[allEventDays[-2]]
|
|
last_days_event = last_day_data['eventslist'][-1]
|
|
last_days_event['end'] = (result.end-1).latestTime().Time()
|
|
else:
|
|
eventDays[eventEndDay]['eventslist'].append(
|
|
{ 'end': event['end'],
|
|
'start': None,
|
|
'title': event['title'],
|
|
'type': event['type'],
|
|
'id': event['id']} )
|
|
eventDays[eventEndDay]['event'] = 1
|
|
else:
|
|
eventDays[eventStartDay]['eventslist'].append(event)
|
|
eventDays[eventStartDay]['event'] = 1
|
|
# This list is not uniqued and isn't sorted
|
|
# uniquing and sorting only wastes time
|
|
# and in this example we don't need to because
|
|
# later we are going to do an 'if 2 in eventDays'
|
|
# so the order is not important.
|
|
# example: [23, 28, 29, 30, 31, 23]
|
|
return eventDays
|
|
|
|
|
|
def getDailyEventsForMonth(self, month, year):
|
|
year = int(year)
|
|
month = int(month)
|
|
daysByWeek = self.calendar._getCalendar().monthcalendar(year, month)
|
|
weeks = []
|
|
events = self.catalog_getevents(year, month)
|
|
|
|
for week in daysByWeek:
|
|
days = []
|
|
for day in week:
|
|
if events.has_key(day):
|
|
days.append(events[day])
|
|
else:
|
|
days.append({'day': day, 'event': 0, 'eventslist':[]})
|
|
|
|
weeks.append(days)
|
|
|
|
return weeks
|
|
|
|
def getEventsForCalendar(self):
|
|
context = aq_inner(self.context)
|
|
year = self.year
|
|
month = self.month
|
|
weeks = self.getDailyEventsForMonth(month, year)
|
|
for week in weeks:
|
|
for day in week:
|
|
daynumber = day['day']
|
|
if daynumber == 0:
|
|
continue
|
|
day['is_today'] = self.isToday(daynumber)
|
|
if day['event']:
|
|
cur_date = DateTime(year, month, daynumber)
|
|
localized_date = [self._ts.ulocalized_time(cur_date, context=context, request=self.request)]
|
|
day['eventstring'] = '\n'.join(localized_date+[' %s' %
|
|
self.getEventString(e) for e in day['eventslist']])
|
|
day['date_string'] = '%s-%s-%s' % (year, month, daynumber)
|
|
evtype = None
|
|
evid = None
|
|
for event in day['eventslist']:
|
|
if evtype is None:
|
|
evtype = event['type']
|
|
evid = event['id']
|
|
elif evtype != event['type']:
|
|
evtype = 'misc'
|
|
evid = None
|
|
break
|
|
day['eventclass'] = evtype or 'none'
|
|
day['eventid'] = evid
|
|
|
|
return weeks
|
|
|
|
def getEventString(self, event):
|
|
start = event.get('start') and ':'.join(event.get('start').split(':')[:2]) or ''
|
|
end = event.get('end') and ':'.join(event.get('end').split(':')[:2]) or ''
|
|
title = safe_unicode(event.get('title')) or u'event'
|
|
|
|
if start and end:
|
|
eventstring = "%s-%s %s" % (start, end, title)
|
|
elif start: # can assume not event['end']
|
|
eventstring = "%s - %s" % (start, title)
|
|
elif event['end']: # can assume not event['start']
|
|
eventstring = "%s - %s" % (title, end)
|
|
else: # can assume not event['start'] and not event['end']
|
|
eventstring = title
|
|
|
|
return eventstring
|
|
|
|
def getPreviousMonth(self, year, month):
|
|
if month==0 or month==1:
|
|
month, year = 12, year - 1
|
|
else:
|
|
month-=1
|
|
return (year, month)
|
|
|
|
def getNextMonth(self, year, month):
|
|
if month==12:
|
|
month, year = 1, year + 1
|
|
else:
|
|
month+=1
|
|
return (year, month)
|
|
|
|
def getWeekdays(self):
|
|
"""Returns a list of Messages for the weekday names."""
|
|
weekdays = []
|
|
# list of ordered weekdays as numbers
|
|
for day in self.calendar.getDayNumbers():
|
|
weekdays.append(PLMF(self._ts.day_msgid(day, format='s'),
|
|
default=self._ts.weekday_english(day, format='a')))
|
|
|
|
return weekdays
|
|
|
|
def isToday(self, day):
|
|
"""Returns True if the given day and the current month and year equals
|
|
today, otherwise False.
|
|
"""
|
|
return self.now[2]==day and self.now[1]==self.month and \
|
|
self.now[0]==self.year
|
|
|