Attachment 'EventCalendar-093.py'
Download 1 """
2 EventCalendar.py Version 0.93 January 18, 2006
3
4 This macro gives a list of the events recorded in the sub-pages in the form of monthly view and list view.
5
6 @copyright: 2006 by Seungik Lee <seungiklee<at>gmail.com> http://www.silee.net/
7 @license: GPL
8
9 For more information, please visit http://moinmoin.wikiwikiweb.de/MacroMarket/EventCalendar
10
11 Usage:
12 * To list the events in a page, just insert [[EventCalendar]]
13 * To insert an event, insert the event information in any pages of specified category (CategoryEventCalendar by default).
14
15 * For example,
16
17 [default_description:: [default_description_text]]
18 [default_bgcolor:: [default_custom_background_color]]
19
20 == <title> ==
21 start:: <startdate> [starttime]
22 [end:: [enddate] [endtime]]
23 [description:: [description_text]]
24 [bgcolor:: [custom_background_color]]
25 [recur:: <recur_freq> <recur_type> [until <recur_until>]]
26
27 ...
28
29 ----
30 CategoryEventCalendar
31
32
33 * title: event title. required
34 * should be enclosed with heading marker ('='), Title cannot be omitted.
35
36 * startdate: date of start. required
37 * should be in YYYY/MM/DD or YYYY-MM-DD
38
39 * starttime: time of start. optional
40 * should be in HH:MM in 24-hour format
41
42 * enddate: date of end. optional
43 * should be in YYYY/MM/DD or YYYY-MM-DD. If omitted, it will be assigned equal to <startdate>.
44
45 * endtime: time of end. optional
46 * should be in HH:MM in 24-hour format. Both of start|end Time can be omitted but not either of them.
47
48 * description: description of the event. optional
49 * any text with no markup. should be in a line.
50
51 * bgcolor: custom background color of the event in monthly view. optional
52 * e.g., #abcdef
53
54 * recur: recurrence information of the event, optional
55 * recur_freq: how many intervals, digit, required
56 * recur_type: [day|week|weekday|month|year], required
57 * day: every [recur_freq] days
58 * week: every [recur_freq] weeks
59 * weekday: on the same weekday of [recur_freq]-th week of the month
60 * month: on the same day of [recur_freq]-th month
61 * year: on the same day of [recur_freq]-th year
62 * recur_until: recurred until when, YYYY/MM/DD or YYYY-MM-DD, optional
63
64 * e.g., 10 day, 2 week until 2006-06-31, 3 weekday, 6 month until 2007-12-31, 1 year
65
66 * default_bgcolor, default_description: default values of bgcolor and description in the page if unavailable
67
68 * The order of the fields after an event title does not matter.
69
70 Notes:
71 * 'MonthCalendar.py' developed by Thomas Waldmann <ThomasWaldmann@gmx.de> has inspired this macro.
72 * Much buggy.. : please report bugs and suggest your ideas.
73 * If you missed to add css for EventCalender, monthly view may not be readable.
74 * Insert the EventCalendar css classes into the screen.css of an appropriate theme.
75
76
77 Event Data Examples:
78
79 = Default values =
80 default_bgcolor:: #c0c0c0
81 default_description:: testing...
82
83 === Test event ===
84 start:: 2006-01-10 14:00
85 end:: 2006-01-12 17:00
86 description:: test event
87 bgcolor:: #cfcfcf
88
89 === Jinah's Birthday ===
90 start:: 1977-10-20
91 recur:: 1 year
92
93 === Weekly meeting ===
94 start:: 2006-01-17 19:00
95 end:: 21:00
96 recur:: 1 week until 2006-12-31
97
98 ----
99 CategoryEventCalendar
100
101
102 Caching-related Information:
103 * It caches all the page list of the specified category and the event information.
104 * If you added/removed a page into/from a category, you need to do 'Delete cache' in the macro page.
105
106
107 """
108
109 from MoinMoin import wikiutil, config, search, caching
110 from MoinMoin.Page import Page
111 from MoinMoin.parser import wiki
112 import re, calendar, time, datetime
113 import codecs, os, urllib, sha
114
115 try:
116 import cPickle as pickle
117 except ImportError:
118 import pickle
119
120 # Set pickle protocol, see http://docs.python.org/lib/node64.html
121 PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL
122
123
124 # The following line sets the calendar to have either Sunday or Monday as
125 # the first day of the week. Only SUNDAY or MONDAY (case sensitive) are
126 # valid here. All other values will not make good calendars.
127 # XXX change here ----------------vvvvvv
128 calendar.setfirstweekday(calendar.SUNDAY)
129
130
131 class Globs:
132 month_style_us = 1 # 1: October 2005; 2: 2005 / 10
133 defaultcategory = 'CategoryEventCalendar'
134 upcomingrange = 7 # days
135 pagename = ''
136 baseurl = ''
137 subname = ''
138 wkend = ''
139 months = ''
140 wkdays = ''
141 today = ''
142 request = None
143 formatter = None
144 cal_action = ''
145 debugmsg = ''
146 page_action = ''
147 events = None
148
149
150 class Params:
151 menubar = 0
152 monthlywidth = ''
153 simplewidth = ''
154 firstview = ''
155 curdate = ''
156 bgcolor = ''
157 category = ''
158 upcomingrange = 0
159 debug = 0
160
161
162 def execute(macro, args):
163
164 request = macro.request
165 formatter = macro.formatter
166
167 # INITIALIZATION ----------------------------------------
168 setglobalvalues(macro)
169 getparams(args)
170
171 # allowed actions
172 allowed_action = ['monthly', 'list', 'simple', 'upcoming']
173 default_action = Params.firstview
174
175 # Internal variables
176 cal_action = ''
177 form_vals = {}
178
179 # PROCESSING ARGUEMENTS ----------------------------------------
180 if args:
181 args=request.getText(args)
182
183 for item in macro.form.items():
184 if not form_vals.has_key(item[0]):
185 try:
186 form_vals[item[0]]=item[1][0]
187 except AttributeError:
188 pass
189
190 # PROCESSING ACTIONS ----------------------------------------
191 cal_action = form_vals.get('calaction', default_action)
192 page_action = form_vals.get('action', 'show')
193
194 if not cal_action in allowed_action:
195 cal_action = default_action
196
197 form_vals['calaction'] = cal_action
198
199 # CONTROL FUNCTIONS ----------------------------------------
200
201 html = []
202 html_result = ''
203
204 Globs.cal_action = cal_action
205 Globs.page_action = page_action
206
207
208 # redirect to the appropriate view
209 if cal_action == 'monthly':
210 html_result = showcalendar(form_vals)
211
212 if cal_action == 'list':
213 html_result = showeventlist(form_vals)
214
215 if cal_action == 'simple':
216 html_result = showsimplecalendar(form_vals)
217
218 if cal_action == 'upcoming':
219 html_result = showupcomingeventlist(form_vals)
220
221
222 # format output
223 html.append( html_result )
224 html.append( showmenubar(form_vals) )
225
226 if Params.debug and Globs.debugmsg:
227 html.append(u'<p><b>Debug messages:</b><font color="#aa0000"><ol>%s</ol></font>' % Globs.debugmsg)
228
229 return formatter.rawHTML(u''.join(html))
230
231
232
233 def getparams(args):
234 # process arguments
235
236 params = {}
237 if args:
238 # Arguments are comma delimited key=value pairs
239 sargs = args.split(',')
240
241 for item in sargs:
242 sitem = item.split('=')
243
244 if len(sitem) == 2:
245 key, value = sitem[0], sitem[1]
246 params[key.strip()] = value.strip()
247
248 # category name:
249 # default: 'CategoryEventCalendar'
250 Params.category = params.get('category', Globs.defaultcategory)
251
252 # menu bar: shows menubar or not (1: show, 0: no menubar)
253 # default: 1
254 try:
255 Params.menubar = int(params.get('menubar', 1))
256 except (TypeError, ValueError):
257 Params.menubar = 1
258
259 # calendar width in pixel or percent (monthly)
260 # default: 600px
261 Params.monthlywidth = params.get('monthlywidth', '600')
262 if Params.monthlywidth:
263 # Params.monthlywidth = Params.monthlywidth.replace('%', '%%')
264 Params.monthlywidth = ' width="%s" ' % Params.monthlywidth
265
266 # calendar width in pixel or percent (simply)
267 # default: 150px
268 Params.simplewidth = params.get('simplewidth', '150')
269 if Params.simplewidth:
270 # Params.simplewidth = Params.simplewidth.replace('%', '%%')
271 Params.simplewidth = ' width="%s" ' % Params.simplewidth
272
273 # calendar view: monthly, list, simple
274 # default: 'monthly'
275 Params.firstview = params.get('firstview', 'monthly')
276
277 # calendar date: in YYYYMM format (in monthly, simple view)
278 # default: current month
279 Params.curdate = params.get('curdate', '')
280
281 # upcoming range: # of days for upcoming event list
282 # default: 7
283 try:
284 Params.upcomingrange = int(params.get('upcomingrange', Globs.upcomingrange))
285 except (TypeError, ValueError):
286 Params.upcomingrange = Globs.upcomingrange
287
288 # default bgcolor
289 Params.bgcolor = '#ddffdd'
290
291
292 def setglobalvalues(macro):
293
294 request = macro.request
295 formatter = macro.formatter
296
297 # Useful variables
298 Globs.baseurl = request.getBaseURL() + '/'
299 Globs.pagename = formatter.page.page_name
300 Globs.request = request
301 Globs.formatter = formatter
302
303 # This fixes the subpages bug. subname is now used instead of pagename when creating certain urls
304 Globs.subname = Globs.pagename.split('/')[-1]
305
306 pagepath = formatter.page.getPagePath()
307 Globs.pagepath = formatter.page.getPagePath()
308
309 # european / US differences
310 months = ('January','February','March','April','May','June','July','August','September','October','November','December')
311
312 # Set things up for Monday or Sunday as the first day of the week
313 if calendar.firstweekday() == calendar.MONDAY:
314 wkend = 6
315 wkdays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')
316 elif calendar.firstweekday() == calendar.SUNDAY:
317 wkend = 0
318 wkdays = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
319
320 Globs.months = months
321 Globs.wkdays = wkdays
322 Globs.wkend = wkend
323
324 year, month, day, h, m, s, wd, yd, ds = request.user.getTime(time.time())
325 Globs.today = datetime.date(year, month, day)
326
327 Globs.debugmsg = ''
328
329
330 def showReferPageParsed(event, targettext='title', showdesc=0):
331 request = Globs.request
332 pagename = Globs.pagename
333
334 refer = event['refer']
335 targettext = event[targettext]
336 startdate = event['startdate']
337 enddate = event['enddate']
338 description = event['description']
339 starttime = event['starttime']
340 endtime = event['endtime']
341 hid = event['hid']
342
343 if showdesc:
344 if (startdate == enddate) and (starttime and endtime):
345 timedescription = '%s:%s ~ %s:%s' % (starttime[:2], starttime[2:], endtime[:2], endtime[2:])
346 if description:
347 timedescription = '%s | ' % timedescription
348 else:
349 timedescription = ''
350
351 targetlink = '<a href="%s#%s" title="%s%s">%s</a>' % ( refer, hid, timedescription, wikiutil.escape(description), wikiutil.escape(targettext) )
352 else:
353 targetlink = '<a href="%s#%s">%s</a>' % ( refer, hid, wikiutil.escape(targettext))
354
355 return targetlink
356
357
358 def getheadingid(request, referpage, title):
359
360 pntt = (referpage + title).encode(config.charset)
361 hid = "head-" + sha.new(pntt).hexdigest()
362 request._page_headings.setdefault(pntt, 0)
363 request._page_headings[pntt] += 1
364 if request._page_headings[pntt] > 1:
365 hid += '-%d'%(request._page_headings[pntt],)
366
367 return hid
368
369
370 def getquerystring(form_vals, req_fields):
371
372 m_query = []
373 tmp_form_vals = form_vals
374
375 # format querystring
376 # action should be poped out
377 for field in req_fields:
378 if tmp_form_vals.has_key(field):
379 m_query.append(u'%s=%s' % (field, tmp_form_vals[field]) )
380
381 if 'prevcalaction' in req_fields:
382 if not tmp_form_vals.has_key('prevcalaction'):
383 m_query.append(u'%s=%s' % ('prevcalaction', tmp_form_vals['calaction']) )
384
385 m_query = u'&'.join(m_query)
386 return m_query
387
388
389 # bottom menu bar
390 def showmenubar(form_vals):
391
392 cal_action = Globs.cal_action
393 page_name = Globs.pagename
394
395 if not Params.menubar: return ''
396
397 if cal_action == 'simple':
398 menuwidth = Params.simplewidth
399 elif cal_action == 'monthly':
400 menuwidth = Params.monthlywidth
401 else:
402 menuwidth = ''
403
404 left_menu_selected = []
405 right_menu_selected = []
406
407 # Go Today
408 year, month, day = gettodaydate()
409 mnu_curmonthcal = u'<a href="%s?calaction=%s&caldate=%d%02d" title="Go Today">[Today]</a>' % (page_name, cal_action, year, month)
410
411 # List View
412 mnu_listview = u'<a href="%s?calaction=list" title="List of all events">[List]</a>' % page_name
413
414 # Monthly View
415 mnu_monthview = u'<a href="%s?calaction=monthly&%s" title="Monthly view">[Monthly]</a>' % (page_name, getquerystring(form_vals, ['caldate']) )
416
417 # Simple Calendar View
418 mnu_simpleview = u'<a href="%s?calaction=simple&%s" title="Simple calendar view">[Simple]</a>' % (page_name, getquerystring(form_vals, ['caldate']) )
419
420 # Upcoming Event List
421 mnu_upcomingview = u'<a href="%s?calaction=upcoming&%s" title="Upcoming event list">[Upcoming]</a>' % (page_name, getquerystring(form_vals, ['caldate']) )
422
423 html = [
424 u'\r\n',
425 u'<table class="eventcalendar_menubar" %s>',
426 u' <tr>',
427 u' <td class="eventcalendar_menubar" align="left">%s</td>',
428 u' <td class="eventcalendar_menubar" align="right">%s</td>',
429 u' </tr>',
430 u'</table>',
431 ]
432
433 if cal_action == 'list':
434 left_menu_selected.append(mnu_monthview)
435 left_menu_selected.append(mnu_simpleview)
436 right_menu_selected.append(mnu_upcomingview)
437
438 elif cal_action == 'simple':
439 left_menu_selected.append(mnu_monthview)
440 left_menu_selected.append(mnu_listview)
441 right_menu_selected.append(mnu_upcomingview)
442 right_menu_selected.append(mnu_curmonthcal)
443
444 elif cal_action == 'upcoming':
445 left_menu_selected.append(mnu_monthview)
446 left_menu_selected.append(mnu_simpleview)
447 left_menu_selected.append(mnu_listview)
448
449 else:
450 left_menu_selected.append(mnu_listview)
451 left_menu_selected.append(mnu_simpleview)
452 right_menu_selected.append(mnu_upcomingview)
453 right_menu_selected.append(mnu_curmonthcal)
454
455 left_menu_selected = u'\r\n'.join(left_menu_selected)
456 right_menu_selected = u'\r\n'.join(right_menu_selected)
457
458 html = u'\r\n'.join(html)
459 html = html % (menuwidth, left_menu_selected, right_menu_selected)
460
461 return html
462
463
464 def getdatefield(str_date):
465 str_year = ''
466 str_month = ''
467 str_day = ''
468
469 if len(str_date) == 6:
470 # year+month
471 str_year = str_date[:4]
472 str_month = str_date[4:]
473 str_day = '1'
474
475 elif len(str_date) == 8:
476 # year+month+day
477 str_year = str_date[:4]
478 str_month = str_date[4:6]
479 str_day = str_date[6:]
480
481 elif len(str_date) == 10:
482 # year+?+month+?+day
483 str_year = str_date[:4]
484 str_month = str_date[5:7]
485 str_day = str_date[8:]
486
487 else:
488 raise ValueError
489
490 # It raises exception if the input date is incorrect
491 temp = datetime.date(int(str_year), int(str_month), int(str_day))
492
493 return temp.year, temp.month, temp.day
494
495
496 def gettimefield(str_time):
497 str_hour = ''
498 str_min = ''
499
500 if len(str_time) == 4:
501 # hour+minute
502 str_hour = str_time[:2]
503 str_min = str_time[2:]
504
505 elif len(str_time) == 5:
506 # hour+?+minute
507 str_hour = str_time[:2]
508 str_min = str_time[3:]
509
510 else:
511 raise ValueError
512
513 # It raises exception if the input date is incorrect
514 temp = datetime.time(int(str_hour), int(str_min))
515
516 return temp.hour, temp.minute
517
518
519 def gettodaydate():
520 today = Globs.today
521 return today.year, today.month, today.day
522
523
524 def cal_listhead():
525
526 html = [
527 u' <tr>',
528 u' <td class="list_head">Title</td>',
529 u' <td class="list_head">Start Date</td>',
530 u' <td class="list_head">End Date</td>',
531 u' <td class="list_head">Recurrence</td>',
532 u' <td class="list_head">Description</td>',
533 u' <td class="list_head">Reference</td>',
534 u' </tr>',
535 ]
536
537 return u'\r\n'.join(html)
538
539
540 def showeventlist(form_vals):
541
542 debug('Show Calendar: List view')
543
544 request = Globs.request
545 formatter = Globs.formatter
546
547 html_event_rows = []
548 html_list_header = cal_listhead()
549
550 # read all the events
551 events, cal_events = loadEvents()
552
553 # sort events
554 sorted_eventids = events.keys()
555 sorted_eventids.sort(cmp=lambda x,y: cmp(events[x]['startdate'], events[y]['startdate']))
556
557 for eid in sorted_eventids:
558 if not events[eid]['clone']:
559 html_event_rows.append( listshow_event(events[eid], form_vals) )
560
561 html_event_rows = u'\r\n'.join(html_event_rows)
562
563 html_list_table = [
564 u'\r\n<div id="eventlist">',
565 u'<table class="eventlist">',
566 u'%s' % html_list_header,
567 u'%s' % html_event_rows,
568 u'</table>',
569 u'</div>',
570 ]
571 html_list_table = u'\r\n'.join(html_list_table)
572
573 return html_list_table
574
575
576 def listshow_event(event, form_vals):
577
578 if event['recur_freq']:
579 recur_desc = 'every %d %s' % (event['recur_freq'], event['recur_type'])
580 if event['recur_until']:
581 recur_desc = '%s until %s' % (recur_desc, formatcfgdatetime(event['recur_until']))
582 else:
583 recur_desc = ''
584
585 html = [
586 u' <tr>',
587 u' <td class="list_entry">%s</td>' % converttext(event['title']),
588 u' <td class="list_entry">%s</td>' % formatcfgdatetime(event['startdate'], event['starttime']),
589 u' <td class="list_entry">%s</td>' % formatcfgdatetime(event['enddate'], event['endtime']),
590 u' <td class="list_entry">%s</td>' % recur_desc,
591 u' <td class="list_entry">%s</td>' % converttext(event['description']),
592 u' <td class="list_entry">%s</td>' % showReferPageParsed(event, 'refer'),
593 u' </tr>',
594 ]
595
596 return u'\r\n'.join(html)
597
598
599 def showupcomingeventlist(form_vals):
600
601 debug('Show Calendar: Upcoming Event View')
602
603 request = Globs.request
604 formatter = Globs.formatter
605
606 html_event_rows = []
607 html_list_header = cal_listhead()
608
609 year, month, day = gettodaydate()
610 day_delta = datetime.timedelta(days=Params.upcomingrange)
611 cur_date = datetime.date(year, month, day)
612 next_range = cur_date + day_delta
613
614 # set ranges of events
615 datefrom = u'%04d%02d%02d' % (year, month, day)
616 dateto = u'%04d%02d%02d' % (next_range.year, next_range.month, next_range.day)
617
618 # read all the events (no cache)
619 events, cal_events = loadEvents(datefrom, dateto, 1)
620
621 datefrom = u'%04d-%02d-%02d' % (year, month, day)
622 dateto = u'%04d-%02d-%02d' % (next_range.year, next_range.month, next_range.day)
623
624 # sort events
625 sorted_eventids = events.keys()
626 sorted_eventids.sort(cmp=lambda x,y: cmp(events[x]['startdate'], events[y]['startdate']))
627
628 for eid in sorted_eventids:
629 html_event_rows.append( listshow_event(events[eid], form_vals) )
630
631 html_event_rows = u'\r\n'.join(html_event_rows)
632
633 html_list_table = [
634 u'\r\n<div id="eventlist">',
635 u'<table class="eventlist">',
636 u'<tr><td colspan="7" class="list_entry" style="border-width: 0px;"><b>Upcoming Event List: %s ~ %s</b><p><br><p></td></tr>' % (datefrom, dateto),
637 u'%s' % html_list_header,
638 u'%s' % html_event_rows,
639 u'</table>',
640 u'</div>',
641 ]
642 html_list_table = u'\r\n'.join(html_list_table)
643
644 return html_list_table
645
646
647
648
649 def showcalendar(form_vals):
650
651 request = Globs.request
652 formatter = Globs.formatter
653
654 if form_vals.has_key('caldate'):
655 try:
656 year, month, str_temp = getdatefield(form_vals['caldate'])
657 except (TypeError, ValueError):
658 debug('Invalid target date: e.g., "200510"')
659 year, month, dy = gettodaydate()
660 elif Params.curdate:
661 try:
662 year, month, str_temp = getdatefield(Params.curdate)
663 except (TypeError, ValueError):
664 debug('Invalid target date: e.g., "200510"')
665 year, month, dy = gettodaydate()
666
667 else:
668 year, month, dy = gettodaydate()
669
670 html = showeventcalendar(year, month)
671
672 return u''.join(html)
673
674
675
676
677 def showsimplecalendar(form_vals):
678
679 request = Globs.request
680 formatter = Globs.formatter
681
682 if form_vals.has_key('caldate'):
683 try:
684 year, month, str_temp = getdatefield(form_vals['caldate'])
685 except (TypeError, ValueError):
686 debug('Invalid target date: e.g., "200510"')
687 year, month, dy = gettodaydate()
688 elif Params.curdate:
689 try:
690 year, month, str_temp = getdatefield(Params.curdate)
691 except (TypeError, ValueError):
692 debug('Invalid target date: e.g., "200510"')
693 year, month, dy = gettodaydate()
694 else:
695 year, month, dy = gettodaydate()
696
697 html = showsimpleeventcalendar(year, month)
698
699 return u''.join(html)
700
701
702
703 # sort events in cal_events by length of days of the event
704 def comp_cal_events(xid, yid):
705 events = Globs.events
706
707 if events[xid]['date_len'] > events[yid]['date_len']:
708 return -1
709 elif events[xid]['date_len'] == events[yid]['date_len']:
710 if events[xid]['date_len'] == 1:
711 return cmp(events[xid]['starttime'], events[yid]['starttime'])
712 else:
713 return 0
714 else:
715 return 1
716
717
718 # load events from wiki pages
719 def loadEvents(datefrom='', dateto='', nocache=0):
720
721 request = Globs.request
722
723 debug('Loading event information.')
724
725 events = {}
726 cal_events = {}
727 raw_events = loadEventsFromWikiPages()
728
729 # handling cal_events
730 if datefrom or dateto:
731
732 # cache configurations
733 arena = Page(request, Globs.pagename)
734 eventkey = 'events'
735 filteredeventkey = 'events_%s-%s' % (datefrom, dateto)
736 caleventkey = 'calevents_%s-%s' % (datefrom, dateto)
737
738 cache_events = caching.CacheEntry(request, arena, eventkey)
739 cache_filteredevents = caching.CacheEntry(request, arena, filteredeventkey)
740 cache_calevents = caching.CacheEntry(request, arena, caleventkey)
741
742 dirty = 1
743
744 debug('Checking cal_events cache')
745
746 if not (cache_calevents.needsUpdate(cache_events._filename()) or cache_filteredevents.needsUpdate(cache_events._filename())):
747
748 try:
749 events = pickle.loads(cache_filteredevents.content())
750 cal_events = pickle.loads(cache_calevents.content())
751 debug('Cached event (filtered) information is used: total %d events' % len(events))
752 dirty = 0
753 except (pickle.UnpicklingError, IOError, EOFError, ValueError):
754 debug('Picke error at fetching cached events (filtered)')
755 events = {}
756 cal_events = {}
757
758
759 # if cache is dirty, update the cache
760 if dirty:
761
762 debug('Checking event cache: it\'s dirty or requested to refresh')
763 debug('Building new cal_event information')
764
765 try:
766 datefrom, dateto = int(datefrom), int(dateto)
767 except (TypeError, ValueError):
768 datefrom, dateto = 0, 0
769
770 clone_num = 0
771
772 for e_id in raw_events.keys():
773
774 cur_event = raw_events[e_id]
775
776 # handling event recurrence
777 recur_freq = cur_event['recur_freq']
778
779 if recur_freq:
780
781 if not (cur_event['recur_until'] and int(cur_event['recur_until']) < datefrom) or int(cur_event['startdate']) > dateto:
782
783 # generating cal_events for iteself
784 events[e_id] = cur_event.copy()
785 insertcalevents(cal_events, datefrom, dateto, e_id, cur_event['startdate'], cur_event['enddate'])
786
787 delta_date_len = datetime.timedelta(days = int(cur_event['date_len']) - 1 )
788
789 if cur_event['recur_type'] == 'day':
790
791 day_delta = int(recur_freq)
792 startdate = getdatetimefromstring(cur_event['startdate'])
793 datefrom_date = getdatetimefromstring(datefrom)
794
795 if int(datefrom) > int(cur_event['startdate']):
796 diffs = datefrom_date - startdate
797 q_delta = diffs.days / day_delta
798 if diffs.days % day_delta > 0:
799 q_delta += 1
800 else:
801 q_delta = 1
802
803 while 1:
804
805 if q_delta == 0:
806 q_delta += 1
807 continue
808
809 recurred_startdate = startdate + datetime.timedelta(days = q_delta * day_delta )
810 recurred_enddate = recurred_startdate + delta_date_len
811
812 new_startdate = formatdateobject(recurred_startdate)
813 new_enddate = formatdateobject(recurred_enddate)
814
815 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
816 break
817
818 clone_num += 1
819 clone_id = 'c%d' % clone_num
820
821 events[clone_id] = cur_event.copy()
822 events[clone_id]['id'] = clone_id
823 events[clone_id]['startdate'] = new_startdate
824 events[clone_id]['enddate'] = new_enddate
825 events[clone_id]['clone'] = 1
826
827 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
828
829 q_delta += 1
830
831 elif cur_event['recur_type'] == 'week':
832
833 day_delta = int(recur_freq) * 7
834
835 startdate = getdatetimefromstring(cur_event['startdate'])
836 datefrom_date = getdatetimefromstring(datefrom)
837
838 if int(datefrom) > int(cur_event['startdate']):
839 diffs = datefrom_date - startdate
840 q_delta = diffs.days / day_delta
841 if diffs.days % day_delta > 0:
842 q_delta += 1
843 else:
844 q_delta = 1
845
846 while 1:
847
848 if q_delta == 0:
849 q_delta += 1
850 continue
851
852 recurred_startdate = startdate + datetime.timedelta(days = q_delta * day_delta )
853 recurred_enddate = recurred_startdate + delta_date_len
854
855 new_startdate = formatdateobject(recurred_startdate)
856 new_enddate = formatdateobject(recurred_enddate)
857
858 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
859 break
860
861 clone_num += 1
862 clone_id = 'c%d' % clone_num
863
864 events[clone_id] = cur_event.copy()
865 events[clone_id]['id'] = clone_id
866 events[clone_id]['startdate'] = new_startdate
867 events[clone_id]['enddate'] = new_enddate
868 events[clone_id]['clone'] = 1
869
870 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
871
872 q_delta += 1
873
874
875 elif cur_event['recur_type'] == 'weekday':
876
877 syear, smonth, sday = getdatefield(cur_event['startdate'])
878 cyear, cmonth, cday = getdatefield(str(datefrom))
879
880 recur_weekday = calendar.weekday(syear, smonth, sday)
881
882
883 while 1:
884
885 firstweekday, daysinmonth = calendar.monthrange(cyear, cmonth)
886 firstmatch = (recur_weekday - firstweekday) % 7 + 1
887
888 #XXX should handle error
889 try:
890 therecur_day = xrange(firstmatch, daysinmonth + 1, 7)[recur_freq-1]
891 except IndexError:
892 therecur_day = xrange(firstmatch, daysinmonth + 1, 7)[-1]
893
894 recurred_startdate = datetime.date(cyear, cmonth, therecur_day)
895 recurred_enddate = recurred_startdate + delta_date_len
896
897 new_startdate = formatdateobject(recurred_startdate)
898 new_enddate = formatdateobject(recurred_enddate)
899
900 if int(new_startdate) < int(datefrom):
901 cyear, cmonth = yearmonthplusoffset(cyear, cmonth, 1)
902 continue
903
904 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
905 break
906
907 clone_num += 1
908 clone_id = 'c%d' % clone_num
909
910 events[clone_id] = cur_event.copy()
911 events[clone_id]['id'] = clone_id
912 events[clone_id]['startdate'] = new_startdate
913 events[clone_id]['enddate'] = new_enddate
914 events[clone_id]['clone'] = 1
915
916 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
917
918 cyear, cmonth = yearmonthplusoffset(cyear, cmonth, 1)
919
920
921 elif cur_event['recur_type'] == 'month':
922
923 cyear, cmonth, therecurday = getdatefield(cur_event['startdate'])
924
925 while 1:
926
927 cyear, cmonth = yearmonthplusoffset(cyear, cmonth, recur_freq)
928 firstweekday, daysinmonth = calendar.monthrange(cyear, cmonth)
929 recur_day = therecurday
930 if daysinmonth < recur_day:
931 recur_day = daysinmonth
932 new_startdate = formatDate(cyear, cmonth, recur_day)
933
934 if int(new_startdate) < int(datefrom):
935 continue
936
937 recurred_startdate = datetime.date(cyear, cmonth, recur_day)
938 recurred_enddate = recurred_startdate + delta_date_len
939
940 new_startdate = formatdateobject(recurred_startdate)
941 new_enddate = formatdateobject(recurred_enddate)
942
943 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
944 break
945
946 clone_num += 1
947 clone_id = 'c%d' % clone_num
948
949 events[clone_id] = cur_event.copy()
950 events[clone_id]['id'] = clone_id
951 events[clone_id]['startdate'] = new_startdate
952 events[clone_id]['enddate'] = new_enddate
953 events[clone_id]['clone'] = 1
954
955 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
956
957 elif cur_event['recur_type'] == 'year':
958
959 ryear, rmonth, rday = getdatefield(cur_event['startdate'])
960 cyear, cmonth, cday = getdatefield(str(datefrom))
961
962 while 1:
963
964 ryear += recur_freq
965 new_startdate = formatDate(ryear, rmonth, rday)
966
967 if int(new_startdate) < int(datefrom):
968 continue
969
970 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
971 break
972
973 recurred_startdate = datetime.date(ryear, rmonth, rday)
974 recurred_enddate = recurred_startdate + delta_date_len
975
976 new_startdate = formatdateobject(recurred_startdate)
977 new_enddate = formatdateobject(recurred_enddate)
978
979 clone_num += 1
980 clone_id = 'c%d' % clone_num
981
982 events[clone_id] = cur_event.copy()
983 events[clone_id]['id'] = clone_id
984 events[clone_id]['startdate'] = new_startdate
985 events[clone_id]['enddate'] = new_enddate
986 events[clone_id]['clone'] = 1
987
988 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
989
990 else:
991
992 if not (int(cur_event['enddate']) < datefrom or int(cur_event['startdate']) > dateto):
993 events[e_id] = cur_event.copy()
994 insertcalevents(cal_events, datefrom, dateto, e_id, cur_event['startdate'], cur_event['enddate'])
995
996 # cache update
997 if not nocache:
998 cache_filteredevents.update(pickle.dumps(events, PICKLE_PROTOCOL))
999 cache_calevents.update(pickle.dumps(cal_events, PICKLE_PROTOCOL))
1000
1001 else:
1002 events = raw_events
1003
1004
1005 # sort cal_events
1006 # store event list into global variables in order to sort them
1007 Globs.events = events
1008
1009 for eachdate in cal_events.keys():
1010 cal_events[eachdate].sort(comp_cal_events)
1011
1012 debug(u'Total %d of events are loaded finally.' % len(events))
1013
1014 #debug('Events:')
1015 #for key in events.keys():
1016 # debug('__ %s' % events[key])
1017
1018 return events, cal_events
1019
1020
1021
1022 def loadEventsFromWikiPages():
1023
1024 events = {}
1025
1026 eventrecord_list = []
1027 eventpages = []
1028
1029 request = Globs.request
1030 category = Params.category
1031
1032 # cache configurations
1033 arena = Page(request, Globs.pagename)
1034 eventkey = 'events'
1035 pagelistkey = 'eventpages'
1036
1037 cache_events = caching.CacheEntry(request, arena, eventkey)
1038 cache_pages = caching.CacheEntry(request, arena, pagelistkey)
1039
1040
1041 # page list cache
1042
1043 debug('Checking page list cache')
1044
1045 # check the time at which page list cache has been created
1046
1047 cp_mtime = cache_pages.mtime()
1048 timedelta_days = 9999
1049
1050 if cp_mtime:
1051 cp_date = datetime.datetime.fromtimestamp(cp_mtime)
1052 today = datetime.datetime.fromtimestamp(time.time())
1053 datediff = today - cp_date
1054 timedelta_days = datediff.days
1055 debug('Time from page list cache built = %s' % datediff)
1056
1057
1058 if Globs.page_action == 'refresh' or cache_pages.needsUpdate(arena._text_filename()) or timedelta_days >= 1:
1059 categorypages = searchPages(request, category)
1060 for page in categorypages:
1061 eventpages.append(page.page_name)
1062 cache_pages.update('\n'.join(eventpages), True)
1063 debug('New page list is built: %d pages' % len(eventpages))
1064 else:
1065 eventpages = cache_pages.content(True).split('\n')
1066 debug('Cached page list is used: %d pages' % len(eventpages))
1067
1068
1069 # generating events
1070
1071 e_num = 0
1072 dirty = 0
1073 debug_records = {}
1074
1075 # fetch event records from each page in the category
1076 for page_name in eventpages:
1077
1078 p = Page(request, page_name)
1079 e_ref = page_name
1080
1081 eventrecordkey = 'eventrecords'
1082 cache_eventrecords = caching.CacheEntry(request, p, eventrecordkey)
1083
1084 if cache_eventrecords.needsUpdate(p._text_filename()) or Globs.page_action == 'refresh':
1085 dirty = 1
1086 page_content = p.get_raw_body()
1087 eventrecords, e_num = getEventRecordFromPage(page_content, e_ref, e_num)
1088 debug_records[e_ref] = '%d eventrecords are fetched from %s' % (len(eventrecords), e_ref)
1089 cache_eventrecords.update(pickle.dumps(eventrecords, PICKLE_PROTOCOL))
1090 else:
1091 try:
1092 eventrecords = pickle.loads(cache_eventrecords.content())
1093 debug_records[e_ref] = '%d cached eventrecords are used from %s' % (len(eventrecords), e_ref)
1094 except (pickle.UnpicklingError, IOError, EOFError, ValueError):
1095 dirty = 1
1096 page_content = p.get_raw_body()
1097 eventrecords, e_num = getEventRecordFromPage(page_content, e_ref, e_num)
1098 debug_records[e_ref] = '%d eventrecords are fetched from %s due to pickle error' % (len(eventrecords), e_ref)
1099 cache_eventrecords.update(pickle.dumps(eventrecords, PICKLE_PROTOCOL))
1100
1101 eventrecord_list.append(eventrecords)
1102
1103 # if no dirty, just fetch the cache
1104 if not (dirty or Globs.page_action == 'refresh'):
1105
1106 debug('Checking event cache: still valid')
1107
1108 try:
1109 events = pickle.loads(cache_events.content())
1110 debug('Cached event information is used: total %d events' % len(events))
1111 except (pickle.UnpicklingError, IOError, EOFError, ValueError):
1112 debug('Picke error at fetching cached events')
1113 events = {}
1114
1115 else:
1116
1117 debug('Checking event cache: it\'s dirty or requested to refresh')
1118
1119 # if there is no events (if it needs refreshed), generate events dictionary
1120 if not len(events.keys()):
1121
1122 # XXX: just debugging
1123 debug('Bulding new event information')
1124 for page_name in eventpages:
1125 debug(debug_records[page_name])
1126
1127
1128 day_delta = datetime.timedelta(days=1)
1129
1130 for eventrecords in eventrecord_list:
1131
1132 for evtrecord in eventrecords:
1133
1134 e_id = evtrecord['id']
1135
1136 # generating events
1137 events[e_id] = evtrecord
1138 #debug('event %s: %s' % (evtrecord['id'], evtrecord))
1139
1140 # after generating updated events, update the cache
1141 cache_events.update(pickle.dumps(events, PICKLE_PROTOCOL))
1142
1143 debug('Event information is newly built: total %d events' % len(events))
1144
1145 # end of updating events block
1146
1147
1148 return events
1149
1150
1151
1152 def getEventRecordFromPage(pagecontent, referpage, e_num):
1153
1154 request = Globs.request
1155
1156 eventrecords = []
1157 page_bgcolor = ''
1158 page_description = ''
1159
1160 # fetch the page default bgcolor
1161 regex_page_bgcolor = r"""
1162 ^\s+default_bgcolor::\s*
1163 (?P<pagebgcolor>\#[0-9a-fA-F]{6})
1164 \s*
1165 $
1166 """
1167
1168 pattern = re.compile(regex_page_bgcolor, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1169 match = pattern.search(pagecontent)
1170
1171 if match:
1172 page_bgcolor = match.group('pagebgcolor')
1173
1174 # fetch the page default description
1175 regex_page_description = r"""
1176 ^\s+default_description::\s*
1177 (?P<pagedescription>.*?)
1178 $
1179 """
1180
1181 pattern = re.compile(regex_page_description, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1182 match = pattern.search(pagecontent)
1183
1184 if match:
1185 page_description = match.group('pagedescription')
1186
1187
1188 # fetch event item
1189 regex_eventitem = r"""
1190 (?P<eventitem>
1191 (?P<heading>^\s*(?P<hmarker>=+)\s(?P<eventtitle>.*?)\s(?P=hmarker) $)
1192 (?P<eventdetail>.*?
1193 (?=
1194 ^\s*(?P<nexthmarker>=+)\s(?P<nexteventtitle>.*?)\s(?P=nexthmarker) $
1195 | \Z
1196 )
1197 )
1198 )
1199 """
1200
1201 pattern = re.compile(regex_eventitem, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1202 match = pattern.findall(pagecontent)
1203
1204 if match:
1205
1206 for matchitem in match:
1207
1208 eventitem = {}
1209
1210 eventtitle = matchitem[3]
1211 eventdetail = matchitem[4]
1212
1213 try:
1214 e_start_date, e_start_time, e_end_date, e_end_time, e_bgcolor, e_description, e_recur_freq, e_recur_type, e_recur_until = geteventfield(eventdetail)
1215 except (TypeError, ValueError):
1216 #debug('An event data is corrupted: invalid event format')
1217 continue
1218
1219 # set default values
1220 if not e_bgcolor:
1221 e_bgcolor = page_bgcolor
1222
1223 if not e_description:
1224 e_description = page_description
1225
1226 e_num += 1
1227 e_id = 'e%d' % e_num
1228
1229 eventitem['id'] = e_id
1230 eventitem['title'] = eventtitle
1231 eventitem['startdate'] = e_start_date
1232 eventitem['starttime'] = e_start_time
1233 eventitem['enddate'] = e_end_date
1234 eventitem['endtime'] = e_end_time
1235 eventitem['title'] = eventtitle
1236 eventitem['refer'] = referpage
1237 eventitem['bgcolor'] = e_bgcolor
1238 eventitem['description'] = e_description
1239 eventitem['recur_freq'] = e_recur_freq
1240 eventitem['recur_type'] = e_recur_type
1241 eventitem['recur_until'] = e_recur_until
1242
1243 eventitem['date_len'] = diffday(e_start_date, e_end_date) + 1
1244 eventitem['clone'] = 0
1245 eventitem['hid'] = getheadingid(request, referpage, eventtitle)
1246
1247 eventrecords.append(eventitem)
1248
1249 #debug('matched records: %d' % len(match))
1250
1251 return eventrecords, e_num
1252
1253
1254
1255 def geteventfield(detail):
1256
1257 regex_startdate = r"""
1258 ^\s+start::\s*
1259 (?P<startdate>\d{4}[/-]\d{2}[/-]\d{2})
1260 \s*
1261 (?P<starttime>\d{2}[:]\d{2})*
1262 \s*
1263 $
1264 """
1265
1266 regex_enddate = r"""
1267 ^\s+end::\s*
1268 (?P<enddate>\d{4}[/-]\d{2}[/-]\d{2})*
1269 \s*
1270 (?P<endtime>\d{2}[:]\d{2})*
1271 \s*
1272 $
1273 """
1274
1275 regex_bgcolor = r"""
1276 ^\s+bgcolor::\s*
1277 (?P<bgcolor>\#[0-9a-fA-F]{6})
1278 \s*
1279 $
1280 """
1281
1282 regex_description = r"""
1283 ^\s+description::\s*
1284 (?P<description>.*?)
1285 $
1286 """
1287
1288 regex_recur = r"""
1289 ^\s+recur::\s*
1290 (?P<recur_freq>\d+)
1291 \s*
1292 (?P<recur_type>day|week|weekday|month|year)
1293 \s*
1294 (
1295 until
1296 \s*
1297 (?P<recur_until>\d{4}[/-]\d{2}[/-]\d{2})
1298 )*
1299 $
1300 """
1301
1302 # need help on regular expressions for more efficient/flexible form
1303
1304 # compile regular expression objects
1305
1306 pattern_startdate = re.compile(regex_startdate, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1307 pattern_enddate = re.compile(regex_enddate, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1308 pattern_bgcolor = re.compile(regex_bgcolor, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1309 pattern_description = re.compile(regex_description, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1310 pattern_recur = re.compile(regex_recur, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1311
1312 ##################### retrieve startdate
1313 match = pattern_startdate.search(detail)
1314
1315 if match:
1316 startdate = match.group('startdate')
1317 starttime = match.group('starttime')
1318 else:
1319 startdate = ''
1320 starttime = ''
1321
1322 ##################### retrieve enddate
1323 match = pattern_enddate.search(detail)
1324
1325 if match:
1326 enddate = match.group('enddate')
1327 endtime = match.group('endtime')
1328 else:
1329 enddate = ''
1330 endtime = ''
1331
1332 ##################### retrieve bgcolor
1333 match = pattern_bgcolor.search(detail)
1334
1335 if match:
1336 bgcolor = match.group('bgcolor')
1337 else:
1338 bgcolor = ''
1339
1340 ##################### retrieve description
1341 match = pattern_description.search(detail)
1342
1343 if match:
1344 description = match.group('description')
1345 else:
1346 description = ''
1347
1348 ##################### retrieve recurrence
1349 match = pattern_recur.search(detail)
1350
1351 if match:
1352 recur_freq = int(match.group('recur_freq'))
1353 recur_type = match.group('recur_type')
1354 recur_until = match.group('recur_until')
1355
1356 else:
1357 recur_freq = 0
1358 recur_type = ''
1359 recur_until = ''
1360
1361
1362 # check validity of each fields
1363
1364 if not startdate:
1365 #debug('start date is not specified')
1366 # self.printoutput('Parse Error', msg, '')
1367 # ERROR
1368 return '','','','','','','','','',''
1369
1370 if (starttime or endtime) and not (starttime and endtime):
1371 #debug('no or 2 time field should be specified')
1372 # ERROR
1373 return '','','','','','','','','',''
1374
1375 # if no time, it's 1-day event
1376 if not enddate:
1377 enddate = startdate
1378
1379 try:
1380 syear, smonth, sday = getdatefield(startdate)
1381 eyear, emonth, eday = getdatefield(enddate)
1382 except (TypeError, ValueError):
1383 #debug('invalid date format: %s, %s' % (startdate, enddate))
1384 return '','','','','','','','','',''
1385
1386 if datetime.date(syear, smonth, sday) > datetime.date(eyear, emonth, eday):
1387 #debug('startdate should precede enddate')
1388 return '','','','','','','','','',''
1389
1390 # format date
1391 startdate = formatDate(syear, smonth, sday)
1392 enddate = formatDate(eyear, emonth, eday)
1393
1394 if (starttime and endtime):
1395 try:
1396 shour, smin = gettimefield(starttime)
1397 ehour, emin = gettimefield(endtime)
1398 except (TypeError, ValueError):
1399 #debug('invalid time format: %s, %s' % (startdate, enddate))
1400 return '','','','','','','','','',''
1401
1402 if startdate == enddate:
1403 if datetime.time(shour, smin) > datetime.time(ehour, emin):
1404 #debug('starttime should precede endtime')
1405 return '','','','','','','','','',''
1406
1407 # format time
1408 starttime = u'%02d%02d' %(shour, smin)
1409 endtime = u'%02d%02d' %(ehour, emin)
1410
1411 # check recurrent data
1412 event_len = diffday(startdate, enddate)
1413 if recur_freq:
1414
1415 if recur_type == 'day':
1416 if event_len > int(recur_freq):
1417 debug('event length should be smaller than recurrence interval')
1418 return '','','','','','','','','',''
1419
1420 elif recur_type == 'week':
1421 if event_len > int(recur_freq) * 7:
1422 debug('event length should be smaller than recurrence interval')
1423 return '','','','','','','','','',''
1424
1425 elif recur_type == 'weekday':
1426 if event_len > 25:
1427 debug('event length should be smaller than recurrence interval')
1428 return '','','','','','','','','',''
1429
1430 elif recur_type == 'month':
1431 if event_len > int(recur_freq) * 25:
1432 debug('event length should be smaller than recurrence interval')
1433 return '','','','','','','','','',''
1434
1435 elif recur_type == 'year':
1436 if event_len > int(recur_freq) * 365:
1437 debug('event length should be smaller than recurrence interval')
1438 return '','','','','','','','','',''
1439
1440 if recur_until:
1441 try:
1442 ryear, rmonth, rday = getdatefield(recur_until)
1443 except (TypeError, ValueError):
1444 debug('invalid date format: %s' % recur_until)
1445 return '','','','','','','','','',''
1446
1447 recur_until = formatDate(ryear, rmonth, rday)
1448
1449 if int(recur_until) < int(enddate):
1450 debug('recur_until should precede enddate')
1451 return '','','','','','','','','',''
1452
1453 return startdate, starttime, enddate, endtime, bgcolor, description, recur_freq, recur_type, recur_until
1454
1455
1456
1457 def converttext(targettext):
1458 # Converts some special characters of html to plain-text style
1459 # What else to handle?
1460
1461 targettext = targettext.replace(u'&', '&')
1462 targettext = targettext.replace(u'>', '>')
1463 targettext = targettext.replace(u'<', '<')
1464 targettext = targettext.replace(u'\n', '<br>')
1465 targettext = targettext.replace(u'"', '"')
1466 targettext = targettext.replace(u'\t', '  ')
1467 targettext = targettext.replace(u' ', ' ')
1468
1469 return targettext
1470
1471
1472 # monthly view
1473 def showeventcalendar(year, month):
1474
1475 debug('Show Calendar: Monthly View')
1476
1477 request = Globs.request
1478 formatter = Globs.formatter
1479 _ = request.getText
1480
1481 wkend = Globs.wkend
1482 months= Globs.months
1483 wkdays = Globs.wkdays
1484
1485 # get the calendar
1486 monthcal = calendar.monthcalendar(year, month)
1487
1488 # shows current year & month
1489 html_header_curyearmonth = calhead_yearmonth(year, month, 'head_yearmonth')
1490
1491 r7 = range(7)
1492
1493 # shows header of week days
1494 html_header_weekdays = []
1495
1496 for wkday in r7:
1497 wday = _(wkdays[wkday])
1498 html_header_weekdays.append( calhead_weekday(wday, 'head_weekday') )
1499 html_header_weekdays = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays)
1500
1501 # pending events for next row
1502 next_pending = []
1503
1504 # gets previous, next month
1505 day_delta = datetime.timedelta(days=-1)
1506 cur_month = datetime.date(year, month, 1)
1507 prev_month = cur_month + day_delta
1508
1509 day_delta = datetime.timedelta(days=15)
1510 cur_month_end = datetime.date(year, month, 25)
1511 next_month = cur_month_end + day_delta
1512
1513 prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month)
1514 next_monthcal = calendar.monthcalendar(next_month.year, next_month.month)
1515
1516 # shows days
1517 html_week_rows = []
1518
1519 # set ranges of events
1520 datefrom = u'%04d%02d21' % (prev_month.year, prev_month.month)
1521 dateto = u'%04d%02d06' % (next_month.year, next_month.month)
1522
1523 # read all the events
1524 events, cal_events = loadEvents(datefrom, dateto)
1525
1526 #debug(u' events: %s' % events)
1527 #debug(u' cal_events: %s' % cal_events)
1528
1529 for week in monthcal:
1530
1531 # day head rows
1532 html_headday_cols = []
1533 html_events_rows = []
1534
1535 for wkday in r7:
1536
1537 day = week[wkday]
1538
1539 if not day:
1540 if week == monthcal[0]:
1541 nb_day = prev_monthcal[-1][wkday]
1542 else:
1543 nb_day = next_monthcal[0][wkday]
1544
1545 html_headday_cols.append( calhead_day_nbmonth(nb_day) )
1546 else:
1547 html_headday_cols.append( calhead_day(year, month, day, wkday) )
1548
1549 html_headday_row = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols)
1550 html_week_rows.append(html_headday_row)
1551
1552 # dummy rows
1553 html_headdummy_cols = []
1554
1555 for wkday in r7:
1556 day = week[wkday]
1557 if not day:
1558 html_headdummy_cols.append( calshow_blankbox('head_dummy_nbmonth') )
1559 else:
1560 html_headdummy_cols.append( calshow_blankbox('head_dummy') )
1561
1562 html_headdummy_cols = u'\r\n'.join(html_headdummy_cols)
1563 html_week_rows.append(' <tr>\r\n%s </tr>\r\n' % html_headdummy_cols)
1564
1565 # pending events for next row
1566 pending = next_pending
1567 next_pending = []
1568
1569 # show events
1570 while 1:
1571 event_left = 7
1572 colspan = -1
1573 html_events_cols = []
1574
1575 for wkday in r7:
1576
1577 day = week[wkday]
1578
1579 if not day:
1580 if week == monthcal[0]:
1581 cur_date = formatDate(prev_month.year, prev_month.month, prev_monthcal[-1][wkday])
1582 else:
1583 cur_date = formatDate(next_month.year, next_month.month, next_monthcal[0][wkday])
1584 else:
1585 cur_date = formatDate(year, month, day)
1586
1587 # if an event is already displayed with colspan
1588 if colspan > 0:
1589 colspan -= 1
1590 if cal_events.has_key(cur_date) and lastevent in cal_events[cur_date]:
1591 cal_events[cur_date].remove(lastevent)
1592
1593 continue
1594
1595 # if there is any event for this date
1596 if cal_events.has_key(cur_date):
1597 if len(cal_events[cur_date]) > 0:
1598
1599 # if there is any pending event in the previous week
1600 if wkday == 0 and len(pending) > 0:
1601 todo_event_id = pending.pop(0)
1602 if todo_event_id in cal_events[cur_date]:
1603 cur_event = events[todo_event_id]
1604 temp_len = diffday(cur_date, cur_event['enddate']) + 1
1605
1606 # calculate colspan value
1607 if (7-wkday) < temp_len:
1608 colspan = 7 - wkday
1609 next_pending.append(cur_event['id'])
1610 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) )
1611
1612 else:
1613 colspan = temp_len
1614 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) )
1615
1616
1617 cal_events[cur_date].remove(todo_event_id)
1618
1619 colspan -= 1
1620 lastevent = todo_event_id
1621 else:
1622 debug('Warning: no such event in cal_events')
1623
1624 continue
1625
1626 # if there is no pending event in the previous week, start a new event
1627 event_found = 0
1628 for e_id in cal_events[cur_date]:
1629
1630 # if the start date of the event is current date
1631 if events[e_id]['startdate'] == cur_date:
1632
1633 cur_event = events[cal_events[cur_date].pop(cal_events[cur_date].index(e_id))]
1634
1635 # calculate colspan value
1636 if (7-wkday) < cur_event['date_len']:
1637 colspan = 7 - wkday
1638 next_pending.append(cur_event['id'])
1639 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'pending', cur_date) )
1640
1641 else:
1642 colspan = cur_event['date_len']
1643 html_events_cols.append( calshow_eventbox(cur_event, colspan, '', cur_date) )
1644
1645 colspan -= 1
1646 lastevent = cur_event['id']
1647 event_found = 1
1648 break
1649
1650 # if the start date of the event is NOT current date
1651 else:
1652
1653 # pending event from previous month
1654 if wkday == 0 and week == monthcal[0]:
1655
1656 cur_event = events[cal_events[cur_date].pop(0)]
1657 temp_len = diffday(cur_date, cur_event['enddate']) + 1
1658
1659 # calculate colspan value
1660 if (7-wkday) < temp_len:
1661 colspan = 7 - wkday
1662 next_pending.append(cur_event['id'])
1663 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) )
1664 else:
1665 colspan = temp_len
1666 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) )
1667
1668 colspan -= 1
1669 lastevent = cur_event['id']
1670 event_found = 1
1671 break
1672
1673 # if there is no event to start
1674 if not event_found:
1675 if not day:
1676 html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1677 else:
1678 html_events_cols.append( calshow_blankbox('cal_noevent') )
1679 event_left -= 1
1680
1681 else:
1682 if not day:
1683 html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1684 else:
1685 html_events_cols.append( calshow_blankbox('cal_noevent') )
1686
1687 event_left -= 1
1688
1689 # if there is NO event for this date
1690 else:
1691 if not day:
1692 html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1693 else:
1694 html_events_cols.append( calshow_blankbox('cal_noevent') )
1695
1696 event_left -= 1
1697
1698 # if no event for this entry
1699 if not event_left:
1700 # ignore the previous entry
1701 break
1702 else:
1703 html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1704
1705 # show dummy blank slots for week height
1706 left_blank_rows = 2 - len(html_events_rows)
1707
1708 # remove the followings
1709 if left_blank_rows > 0 and 0:
1710 for i in range(left_blank_rows):
1711 html_events_cols = []
1712 for wkday in r7:
1713 day = week[wkday]
1714 if not day:
1715 html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1716 else:
1717 html_events_cols.append( calshow_blankbox('cal_noevent') )
1718
1719 html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1720
1721
1722 # close the week slots
1723 html_events_cols = []
1724 for wkday in r7:
1725 day = week[wkday]
1726 if not day:
1727 html_events_cols.append( calshow_blankbox('cal_last_nbmonth') )
1728 else:
1729 html_events_cols.append( calshow_blankbox('cal_last_noevent') )
1730
1731 html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1732
1733 html_events_rows = u'\r\n'.join(html_events_rows)
1734 html_week_rows.append(html_events_rows)
1735
1736 html_calendar_rows = u'\r\n'.join(html_week_rows)
1737
1738 html_cal_table = [
1739 u'\r\n<div id="eventcalendar">',
1740 u'<table class="eventcalendar" %s>' % Params.monthlywidth,
1741 u'%s' % html_header_curyearmonth,
1742 u'%s' % html_header_weekdays,
1743 u'%s' % html_calendar_rows,
1744 u'</table>',
1745 u'</div>',
1746 ]
1747 html_cal_table = u'\r\n'.join(html_cal_table)
1748
1749 return html_cal_table
1750
1751 # simple view
1752 def showsimpleeventcalendar(year, month):
1753
1754 debug('Show Calendar: Simple View')
1755
1756 request = Globs.request
1757 formatter = Globs.formatter
1758 _ = request.getText
1759
1760 wkend = Globs.wkend
1761 months= Globs.months
1762 wkdays = Globs.wkdays
1763
1764 # get the calendar
1765 monthcal = calendar.monthcalendar(year, month)
1766
1767 # shows current year & month
1768 html_header_curyearmonth = calhead_yearmonth(year, month, 'simple_yearmonth')
1769
1770 r7 = range(7)
1771
1772 # shows header of week days
1773 html_header_weekdays = []
1774
1775 for wkday in r7:
1776 wday = wkdays[wkday]
1777 html_header_weekdays.append( calhead_weekday(wday, 'simple_weekday') )
1778 html_header_weekdays = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays)
1779
1780 # gets previous, next month
1781 day_delta = datetime.timedelta(days=-1)
1782 cur_month = datetime.date(year, month, 1)
1783 prev_month = cur_month + day_delta
1784
1785 day_delta = datetime.timedelta(days=15)
1786 cur_month_end = datetime.date(year, month, 25)
1787 next_month = cur_month_end + day_delta
1788
1789 prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month)
1790 next_monthcal = calendar.monthcalendar(next_month.year, next_month.month)
1791
1792 # shows days
1793 html_week_rows = []
1794
1795 # set ranges of events
1796 datefrom = u'%04d%02d21' % (prev_month.year, prev_month.month)
1797 dateto = u'%04d%02d06' % (next_month.year, next_month.month)
1798
1799 # read all the events
1800 events, cal_events = loadEvents(datefrom, dateto)
1801
1802 for week in monthcal:
1803
1804 # day head rows
1805 html_headday_cols = []
1806 html_events_rows = []
1807
1808 for wkday in r7:
1809
1810 day = week[wkday]
1811
1812 if not day:
1813 if week == monthcal[0]:
1814 nb_day = prev_monthcal[-1][wkday]
1815 else:
1816 nb_day = next_monthcal[0][wkday]
1817
1818 html_headday_cols.append( simple_eventbox(year, month, day, nb_day, 'simple_nb') )
1819 else:
1820 cur_date = formatDate(year, month, day)
1821 if cal_events.has_key(cur_date):
1822 html_headday_cols.append( simple_eventbox(year, month, day, wkday, 'simple_event') )
1823 else:
1824 html_headday_cols.append( simple_eventbox(year, month, day, wkday, 'simple_noevent') )
1825
1826 html_headday_row = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols)
1827 html_week_rows.append(html_headday_row)
1828
1829 html_calendar_rows = u'\r\n'.join(html_week_rows)
1830
1831 html_cal_table = [
1832 u'\r\n<div id="eventcalendar">',
1833 u'<table class="simplecalendar" %s>' % Params.simplewidth,
1834 u'%s' % html_header_curyearmonth,
1835 u'%s' % html_header_weekdays,
1836 u'%s' % html_calendar_rows,
1837 u'</table>',
1838 u'</div>',
1839 ]
1840 html_cal_table = u'\r\n'.join(html_cal_table)
1841
1842 return html_cal_table
1843
1844
1845 # show weekday
1846 def calhead_yearmonth(year, month, headclass):
1847
1848 months = Globs.months
1849 monthstyle_us = Globs.month_style_us
1850 cal_action = Globs.cal_action
1851 page_name = Globs.pagename
1852
1853 nextyear, nextmonth = yearmonthplusoffset(year, month, 1)
1854 prevyear, prevmonth = yearmonthplusoffset(year, month, -1)
1855
1856 prevlink = u'%s?calaction=%s&caldate=%d%02d' % (page_name, cal_action, prevyear, prevmonth)
1857 nextlink = u'%s?calaction=%s&caldate=%d%02d' % (page_name, cal_action, nextyear, nextmonth)
1858 curlink = u'%s?calaction=%s&caldate=%d%02d' % (page_name, cal_action, year, month)
1859
1860 if monthstyle_us:
1861 stryearmonth = u'%s %d' % (months[month-1], year)
1862 strnextmonth = u'%s %d' % (months[nextmonth-1], nextyear)
1863 strprevmonth = u'%s %d' % (months[prevmonth-1], prevyear)
1864 else:
1865 stryearmonth = u'%d / %02d' % (year, month)
1866 strnextmonth = u'%d / %02d' % (nextyear, nextmonth)
1867 strprevmonth = u'%d / %02d' % (prevyear, prevmonth)
1868
1869 html = [
1870 u' <tr>',
1871 u' <td class="%s"><a href="%s" title="%s"><</a></td>' % (headclass, prevlink, strprevmonth),
1872 u' <td colspan="5" class="%s"><a href="%s" title="Refresh">%s</a></td>' % (headclass, curlink, stryearmonth),
1873 u' <td class="%s"><a href="%s" title="%s">></a></td>' % (headclass, nextlink, strnextmonth),
1874 u' </tr>',
1875 ]
1876
1877 return u'\r\n'.join(html)
1878
1879 # show days in simple
1880 def simple_eventbox(year, month, day, wkday, boxclass):
1881 wkend = Globs.wkend
1882 if wkday == wkend:
1883 html_text = u'<font color="#aa7744">%s</font>' % day
1884 else:
1885 html_text = u'%s' % day
1886
1887 cyear, cmonth, cday = gettodaydate()
1888
1889 if boxclass == 'simple_nb':
1890 html = u' <td class="%s"> </td>\r\n' % boxclass
1891 else:
1892 if cyear == year and cmonth == month and cday == day:
1893 html = u' <td class="%s_today">%s</td>\r\n' % (boxclass, html_text)
1894 else:
1895 html = u' <td class="%s">%s</td>\r\n' % (boxclass, html_text)
1896
1897 return html
1898
1899
1900 # show weekday
1901 def calhead_weekday(wday, headclass):
1902 if headclass == 'simple_weekday':
1903 html = u' <td class="%s">%s</td>\r\n' % (headclass, wday[0])
1904 else:
1905 html = u' <td class="%s">%s</td>\r\n' % (headclass, wday)
1906
1907 return html
1908
1909
1910 # show days of current month
1911 def calhead_day(year, month, day, wkday):
1912 wkend = Globs.wkend
1913 if wkday == wkend:
1914 html_text = u'<font color="#FF3300">%s</font>' % day
1915 else:
1916 html_text = u'%s' % day
1917
1918 cyear, cmonth, cday = gettodaydate()
1919
1920 if cyear == year and cmonth == month and cday == day:
1921 html = u' <td class="head_day_today"> %s</td>\r\n' % html_text
1922 else:
1923 html = u' <td class="head_day"> %s</td>\r\n' % html_text
1924
1925 return html
1926
1927
1928 # show days of previous or next month
1929 def calhead_day_nbmonth(day):
1930 html = u' <td class="head_day_nbmonth"> %s</td>\r\n' % day
1931 return html
1932
1933
1934 # show blank calendar box
1935 def calshow_blankbox(classname):
1936 html = u' <td class="%s"> </td>' % classname
1937 return html
1938
1939 # show eventbox
1940 def calshow_eventbox(event, colspan, status, cur_date):
1941 if status:
1942 status = u'_%s' % status
1943
1944 title = event['title']
1945 eid = event['id']
1946 startdate = event['startdate']
1947 enddate = event['enddate']
1948 starttime = event['starttime']
1949 endtime = event['endtime']
1950 description = event['description']
1951 bgcolor = event['bgcolor']
1952
1953 year, month, day = getdatefield(cur_date)
1954
1955 if bgcolor:
1956 bgcolor = 'background-color: %s;' % bgcolor
1957 else:
1958 bgcolor = 'background-color: %s;' % Params.bgcolor
1959
1960 if (startdate == enddate) and starttime:
1961 shour, smin = gettimefield(starttime)
1962
1963 link = [
1964 u'<table width="100%%" style="border-width: 0px; padding: 0px; margin: 0px;"><tr>\r\n',
1965 u'<td width="10" nowrap style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top; font-size: 7pt; color: #000000;">%02d:%02d </td>\r\n' % (shour, smin),
1966 u'<td style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top;font-size: 8pt;">',
1967 u'%s' % showReferPageParsed(event, 'title', 1),
1968 u'</td>\r\n</tr></table>',
1969 ]
1970 link = u''.join(link)
1971 else:
1972 link = u'%s' % showReferPageParsed(event, 'title', 1)
1973
1974
1975 html = [
1976 u' <td class="cal_eventbox" colspan="%d"><table class="cal_event">' % colspan,
1977 u' <tr><td id="cal_event_%s" class="cal_event%s" style="%s">%s</td></tr>' % (eid, status, bgcolor, link),
1978 u' </table></td>',
1979 ]
1980
1981 return u'\r\n'.join(html)
1982
1983
1984 def insertcalevents(cal_events, datefrom, dateto, e_id, e_start_date, e_end_date):
1985
1986
1987 if not (int(e_start_date) > dateto or int(e_end_date) < datefrom):
1988
1989 e_start_date = str(max(int(e_start_date), datefrom))
1990 e_end_date = str(min(int(e_end_date), dateto))
1991
1992 day_delta = datetime.timedelta(days=1)
1993 e_start_year, e_start_month, e_start_day = getdatefield(e_start_date)
1994 cur_datetime = datetime.date(e_start_year, e_start_month, e_start_day)
1995
1996 while 1:
1997 tmp_record_date = formatdateobject(cur_datetime)
1998
1999 if not cal_events.has_key(tmp_record_date):
2000 cal_events[tmp_record_date] = []
2001 cal_events[tmp_record_date].append(e_id)
2002
2003 if tmp_record_date == e_end_date:
2004 break
2005
2006 cur_datetime = cur_datetime + day_delta
2007
2008
2009 # date format should be like '20051004' for 2005, Oct., 04
2010 def diffday(date1, date2):
2011
2012 try:
2013 year1, month1, day1 = getdatefield(date1)
2014 year2, month2, day2 = getdatefield(date2)
2015 tmp_diff = datetime.date(year2, month2, day2) - datetime.date(year1, month1, day1)
2016 except (TypeError, ValueError):
2017 debug('An event data is corrupted: invalid date format')
2018 return 0
2019
2020 return tmp_diff.days
2021
2022
2023 def formatDate(year, month, day):
2024 # returns like: '20051004'
2025 return u'%4d%02d%02d' % (year, month, day)
2026
2027 def formatdateobject(obj_date):
2028
2029 return formatDate(obj_date.year, obj_date.month, obj_date.day)
2030
2031
2032 def cliprgb(r,g,b): # don't use 255!
2033 if r < 0: r=0
2034 if r > 254: r=254
2035 if b < 0: b=0
2036 if b > 254: b=254
2037 if g < 0: g=0
2038 if g > 254: g=254
2039 return r, g, b
2040
2041
2042 def debug(astring):
2043 Globs.debugmsg += u'<li>%s\n' % astring
2044
2045
2046 def yearmonthplusoffset(year, month, offset):
2047 month = month+offset
2048 # handle offset and under/overflows - quick and dirty, yes!
2049 while month < 1:
2050 month = month + 12
2051 year = year - 1
2052 while month > 12:
2053 month = month - 12
2054 year = year + 1
2055 return year, month
2056
2057
2058 def formatcfgdatetime(strdate, strtime=''):
2059
2060 if not strdate:
2061 return ''
2062
2063 request = Globs.request
2064
2065 if request.user.date_fmt:
2066 date_fmt = request.user.date_fmt
2067 else:
2068 date_fmt = request.cfg.date_fmt
2069
2070 if request.user.datetime_fmt:
2071 datetime_fmt = request.user.datetime_fmt
2072 else:
2073 datetime_fmt = request.cfg.datetime_fmt
2074
2075 ## XXX HACK
2076 datetime_fmt = datetime_fmt.replace(':%S', '')
2077
2078 date_fmt = str(date_fmt)
2079 datetime_fmt = str(datetime_fmt)
2080
2081 year, month, day = getdatefield(str(strdate))
2082 if strtime:
2083 hour, min = gettimefield(str(strtime))
2084 objdatetime = datetime.datetime(year, month, day, hour, min)
2085 return objdatetime.strftime(datetime_fmt)
2086 else:
2087 objdate = getdatetimefromstring(strdate)
2088 return objdate.strftime(date_fmt)
2089
2090
2091 def getdatetimefromstring(strdate):
2092 year, month, day = getdatefield(str(strdate))
2093 return datetime.date( year, month, day )
2094
2095
2096 def searchPages(request, needle):
2097 # Search the pages and return the results
2098 query = search.QueryParser().parse_query(needle)
2099 results = search.searchPages(request, query)
2100 #results.sortByPagename()
2101
2102 return results.hits
2103
2104 html = []
2105 for page in results.hits:
2106 html.append(page.page_name)
2107
2108 html = u',<br>'.join(html)
2109 return u'%s<p>%s' % (Params.category, html)
2110
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.