Attachment 'EventCalendar-092.py'
Download 1 """
2 EventCalendar.py Version 0.92 January 17, 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">Start Time</td>',
531 u' <td class="list_head">End Date</td>',
532 u' <td class="list_head">End Time</td>',
533 u' <td class="list_head">Recurrence</td>',
534 u' <td class="list_head">Description</td>',
535 u' <td class="list_head">Reference</td>',
536 u' </tr>',
537 ]
538
539 return u'\r\n'.join(html)
540
541
542 def showeventlist(form_vals):
543
544 debug('Show Calendar: List view')
545
546 request = Globs.request
547 formatter = Globs.formatter
548
549 html_event_rows = []
550 html_list_header = cal_listhead()
551
552 # read all the events
553 events, cal_events = loadEvents()
554
555 # sort events
556 sorted_eventids = events.keys()
557 sorted_eventids.sort(cmp=lambda x,y: cmp(events[x]['startdate'], events[y]['startdate']))
558
559 for eid in sorted_eventids:
560 if not events[eid]['clone']:
561 html_event_rows.append( listshow_event(events[eid], form_vals) )
562
563 html_event_rows = u'\r\n'.join(html_event_rows)
564
565 html_list_table = [
566 u'\r\n<div id="eventlist">',
567 u'<table class="eventlist">',
568 u'%s' % html_list_header,
569 u'%s' % html_event_rows,
570 u'</table>',
571 u'</div>',
572 ]
573 html_list_table = u'\r\n'.join(html_list_table)
574
575 return html_list_table
576
577
578 def listshow_event(event, form_vals):
579
580 syear, smonth, sday = getdatefield(event['startdate'])
581 eyear, emonth, eday = getdatefield(event['enddate'])
582
583 if event['starttime']:
584 shour, smin = gettimefield(event['starttime'])
585 ehour, emin = gettimefield(event['endtime'])
586 starttime = '%02d:%02d' % (shour, smin)
587 endtime = '%02d:%02d' % (ehour, emin)
588 else:
589 starttime = ''
590 endtime = ''
591
592 if event['recur_freq']:
593 recur_desc = 'every %d %s' % (event['recur_freq'], event['recur_type'])
594 if event['recur_until']:
595 recur_desc = '%s until %s' % (recur_desc, event['recur_until'])
596 else:
597 recur_desc = ''
598
599 html = [
600 u' <tr>',
601 u' <td class="list_entry">%s</td>' % converttext(event['title']),
602 u' <td class="list_entry">%04d/%02d/%02d</td>' % (syear, smonth, sday),
603 u' <td class="list_entry">%s</td>' % starttime,
604 u' <td class="list_entry">%04d/%02d/%02d</td>' % (eyear, emonth, eday),
605 u' <td class="list_entry">%s</td>' % endtime,
606 u' <td class="list_entry">%s</td>' % recur_desc,
607 u' <td class="list_entry">%s</td>' % converttext(event['description']),
608 u' <td class="list_entry">%s</td>' % showReferPageParsed(event, 'refer'),
609 u' </tr>',
610 ]
611
612 return u'\r\n'.join(html)
613
614
615 def showupcomingeventlist(form_vals):
616
617 debug('Show Calendar: Upcoming Event View')
618
619 request = Globs.request
620 formatter = Globs.formatter
621
622 html_event_rows = []
623 html_list_header = cal_listhead()
624
625 year, month, day = gettodaydate()
626 day_delta = datetime.timedelta(days=Params.upcomingrange)
627 cur_date = datetime.date(year, month, day)
628 next_range = cur_date + day_delta
629
630 # set ranges of events
631 datefrom = u'%04d%02d%02d' % (year, month, day)
632 dateto = u'%04d%02d%02d' % (next_range.year, next_range.month, next_range.day)
633
634 # read all the events (no cache)
635 events, cal_events = loadEvents(datefrom, dateto, 1)
636
637 datefrom = u'%04d-%02d-%02d' % (year, month, day)
638 dateto = u'%04d-%02d-%02d' % (next_range.year, next_range.month, next_range.day)
639
640 # sort events
641 sorted_eventids = events.keys()
642 sorted_eventids.sort(cmp=lambda x,y: cmp(events[x]['startdate'], events[y]['startdate']))
643
644 for eid in sorted_eventids:
645 html_event_rows.append( listshow_event(events[eid], form_vals) )
646
647 html_event_rows = u'\r\n'.join(html_event_rows)
648
649 html_list_table = [
650 u'\r\n<div id="eventlist">',
651 u'<table class="eventlist">',
652 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),
653 u'%s' % html_list_header,
654 u'%s' % html_event_rows,
655 u'</table>',
656 u'</div>',
657 ]
658 html_list_table = u'\r\n'.join(html_list_table)
659
660 return html_list_table
661
662
663
664
665 def showcalendar(form_vals):
666
667 request = Globs.request
668 formatter = Globs.formatter
669
670 if form_vals.has_key('caldate'):
671 try:
672 year, month, str_temp = getdatefield(form_vals['caldate'])
673 except (TypeError, ValueError):
674 debug('Invalid target date: e.g., "200510"')
675 year, month, dy = gettodaydate()
676 elif Params.curdate:
677 try:
678 year, month, str_temp = getdatefield(Params.curdate)
679 except (TypeError, ValueError):
680 debug('Invalid target date: e.g., "200510"')
681 year, month, dy = gettodaydate()
682
683 else:
684 year, month, dy = gettodaydate()
685
686 html = showeventcalendar(year, month)
687
688 return u''.join(html)
689
690
691
692
693 def showsimplecalendar(form_vals):
694
695 request = Globs.request
696 formatter = Globs.formatter
697
698 if form_vals.has_key('caldate'):
699 try:
700 year, month, str_temp = getdatefield(form_vals['caldate'])
701 except (TypeError, ValueError):
702 debug('Invalid target date: e.g., "200510"')
703 year, month, dy = gettodaydate()
704 elif Params.curdate:
705 try:
706 year, month, str_temp = getdatefield(Params.curdate)
707 except (TypeError, ValueError):
708 debug('Invalid target date: e.g., "200510"')
709 year, month, dy = gettodaydate()
710 else:
711 year, month, dy = gettodaydate()
712
713 html = showsimpleeventcalendar(year, month)
714
715 return u''.join(html)
716
717
718
719 # sort events in cal_events by length of days of the event
720 def comp_cal_events(xid, yid):
721 events = Globs.events
722
723 if events[xid]['date_len'] > events[yid]['date_len']:
724 return -1
725 elif events[xid]['date_len'] == events[yid]['date_len']:
726 if events[xid]['date_len'] == 1:
727 return cmp(events[xid]['starttime'], events[yid]['starttime'])
728 else:
729 return 0
730 else:
731 return 1
732
733
734 # load events from wiki pages
735 def loadEvents(datefrom='', dateto='', nocache=0):
736
737 request = Globs.request
738
739 debug('Loading event information.')
740
741 events = {}
742 cal_events = {}
743 raw_events = loadEventsFromWikiPages()
744
745 # handling cal_events
746 if datefrom or dateto:
747
748 # cache configurations
749 arena = Page(request, Globs.pagename)
750 eventkey = 'events'
751 filteredeventkey = 'events_%s-%s' % (datefrom, dateto)
752 caleventkey = 'calevents_%s-%s' % (datefrom, dateto)
753
754 cache_events = caching.CacheEntry(request, arena, eventkey)
755 cache_filteredevents = caching.CacheEntry(request, arena, filteredeventkey)
756 cache_calevents = caching.CacheEntry(request, arena, caleventkey)
757
758 dirty = 1
759
760 debug('Checking cal_events cache')
761
762 if not (cache_calevents.needsUpdate(cache_events._filename()) or cache_filteredevents.needsUpdate(cache_events._filename())):
763
764 try:
765 events = pickle.loads(cache_filteredevents.content())
766 cal_events = pickle.loads(cache_calevents.content())
767 debug('Cached event (filtered) information is used: total %d events' % len(events))
768 dirty = 0
769 except (pickle.UnpicklingError, IOError, EOFError, ValueError):
770 debug('Picke error at fetching cached events (filtered)')
771 events = {}
772 cal_events = {}
773
774
775 # if cache is dirty, update the cache
776 if dirty:
777
778 debug('Checking event cache: it\'s dirty or requested to refresh')
779 debug('Building new cal_event information')
780
781 try:
782 datefrom, dateto = int(datefrom), int(dateto)
783 except (TypeError, ValueError):
784 datefrom, dateto = 0, 0
785
786 clone_num = 0
787
788 for e_id in raw_events.keys():
789
790 cur_event = raw_events[e_id]
791
792 # handling event recurrence
793 recur_freq = cur_event['recur_freq']
794
795 if recur_freq:
796
797 if not (cur_event['recur_until'] and int(cur_event['recur_until']) < datefrom) or int(cur_event['startdate']) > dateto:
798
799 # generating cal_events for iteself
800 events[e_id] = cur_event.copy()
801 insertcalevents(cal_events, datefrom, dateto, e_id, cur_event['startdate'], cur_event['enddate'])
802
803 delta_date_len = datetime.timedelta(days = int(cur_event['date_len']) - 1 )
804
805 if cur_event['recur_type'] == 'day':
806
807 day_delta = int(recur_freq)
808 syear, smonth, sday = getdatefield(cur_event['startdate'])
809 startdate = datetime.date( syear, smonth, sday )
810 fyear, fmonth, fday = getdatefield(str(datefrom))
811 datefrom_date = datetime.date( fyear, fmonth, fday )
812
813 if int(datefrom) > int(cur_event['startdate']):
814 diffs = datefrom_date - startdate
815 q_delta = diffs.days / day_delta
816 if diffs.days % day_delta > 0:
817 q_delta += 1
818 else:
819 q_delta = 1
820
821 while 1:
822
823 if q_delta == 0:
824 q_delta += 1
825 continue
826
827 recurred_startdate = startdate + datetime.timedelta(days = q_delta * day_delta )
828 recurred_enddate = recurred_startdate + delta_date_len
829
830 new_startdate = formatdateobject(recurred_startdate)
831 new_enddate = formatdateobject(recurred_enddate)
832
833 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
834 break
835
836 clone_num += 1
837 clone_id = 'c%d' % clone_num
838
839 events[clone_id] = cur_event.copy()
840 events[clone_id]['id'] = clone_id
841 events[clone_id]['startdate'] = new_startdate
842 events[clone_id]['enddate'] = new_enddate
843 events[clone_id]['clone'] = 1
844
845 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
846
847 q_delta += 1
848
849 elif cur_event['recur_type'] == 'week':
850
851 day_delta = int(recur_freq) * 7
852 syear, smonth, sday = getdatefield(cur_event['startdate'])
853 startdate = datetime.date( syear, smonth, sday )
854 fyear, fmonth, fday = getdatefield(str(datefrom))
855 datefrom_date = datetime.date( fyear, fmonth, fday )
856
857 if int(datefrom) > int(cur_event['startdate']):
858 diffs = datefrom_date - startdate
859 q_delta = diffs.days / day_delta
860 if diffs.days % day_delta > 0:
861 q_delta += 1
862 else:
863 q_delta = 1
864
865 while 1:
866
867 if q_delta == 0:
868 q_delta += 1
869 continue
870
871 recurred_startdate = startdate + datetime.timedelta(days = q_delta * day_delta )
872 recurred_enddate = recurred_startdate + delta_date_len
873
874 new_startdate = formatdateobject(recurred_startdate)
875 new_enddate = formatdateobject(recurred_enddate)
876
877 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
878 break
879
880 clone_num += 1
881 clone_id = 'c%d' % clone_num
882
883 events[clone_id] = cur_event.copy()
884 events[clone_id]['id'] = clone_id
885 events[clone_id]['startdate'] = new_startdate
886 events[clone_id]['enddate'] = new_enddate
887 events[clone_id]['clone'] = 1
888
889 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
890
891 q_delta += 1
892
893
894 elif cur_event['recur_type'] == 'weekday':
895
896 syear, smonth, sday = getdatefield(cur_event['startdate'])
897 cyear, cmonth, cday = getdatefield(str(datefrom))
898
899 recur_weekday = calendar.weekday(syear, smonth, sday)
900
901
902 while 1:
903
904 firstweekday, daysinmonth = calendar.monthrange(cyear, cmonth)
905 firstmatch = (recur_weekday - firstweekday) % 7 + 1
906
907 #XXX should handle error
908 try:
909 therecur_day = xrange(firstmatch, daysinmonth + 1, 7)[recur_freq-1]
910 except IndexError:
911 therecur_day = xrange(firstmatch, daysinmonth + 1, 7)[-1]
912
913 recurred_startdate = datetime.date(cyear, cmonth, therecur_day)
914 recurred_enddate = recurred_startdate + delta_date_len
915
916 new_startdate = formatdateobject(recurred_startdate)
917 new_enddate = formatdateobject(recurred_enddate)
918
919 if int(new_startdate) < int(datefrom):
920 cyear, cmonth = yearmonthplusoffset(cyear, cmonth, 1)
921 continue
922
923 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
924 break
925
926 clone_num += 1
927 clone_id = 'c%d' % clone_num
928
929 events[clone_id] = cur_event.copy()
930 events[clone_id]['id'] = clone_id
931 events[clone_id]['startdate'] = new_startdate
932 events[clone_id]['enddate'] = new_enddate
933 events[clone_id]['clone'] = 1
934
935 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
936
937 cyear, cmonth = yearmonthplusoffset(cyear, cmonth, 1)
938
939
940 elif cur_event['recur_type'] == 'month':
941
942 cyear, cmonth, therecurday = getdatefield(cur_event['startdate'])
943
944 while 1:
945
946 cyear, cmonth = yearmonthplusoffset(cyear, cmonth, recur_freq)
947 firstweekday, daysinmonth = calendar.monthrange(cyear, cmonth)
948 recur_day = therecurday
949 if daysinmonth < recur_day:
950 recur_day = daysinmonth
951 new_startdate = formatDate(cyear, cmonth, recur_day)
952
953 if int(new_startdate) < int(datefrom):
954 continue
955
956 recurred_startdate = datetime.date(cyear, cmonth, recur_day)
957 recurred_enddate = recurred_startdate + delta_date_len
958
959 new_startdate = formatdateobject(recurred_startdate)
960 new_enddate = formatdateobject(recurred_enddate)
961
962 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
963 break
964
965 clone_num += 1
966 clone_id = 'c%d' % clone_num
967
968 events[clone_id] = cur_event.copy()
969 events[clone_id]['id'] = clone_id
970 events[clone_id]['startdate'] = new_startdate
971 events[clone_id]['enddate'] = new_enddate
972 events[clone_id]['clone'] = 1
973
974 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
975
976 elif cur_event['recur_type'] == 'year':
977
978 ryear, rmonth, rday = getdatefield(cur_event['startdate'])
979 cyear, cmonth, cday = getdatefield(str(datefrom))
980
981 while 1:
982
983 ryear += recur_freq
984 new_startdate = formatDate(ryear, rmonth, rday)
985
986 if int(new_startdate) < int(datefrom):
987 continue
988
989 if int(new_startdate) > dateto or (cur_event['recur_until'] and int(cur_event['recur_until']) < int(new_startdate)):
990 break
991
992 recurred_startdate = datetime.date(ryear, rmonth, rday)
993 recurred_enddate = recurred_startdate + delta_date_len
994
995 new_startdate = formatdateobject(recurred_startdate)
996 new_enddate = formatdateobject(recurred_enddate)
997
998 clone_num += 1
999 clone_id = 'c%d' % clone_num
1000
1001 events[clone_id] = cur_event.copy()
1002 events[clone_id]['id'] = clone_id
1003 events[clone_id]['startdate'] = new_startdate
1004 events[clone_id]['enddate'] = new_enddate
1005 events[clone_id]['clone'] = 1
1006
1007 insertcalevents(cal_events, datefrom, dateto, clone_id, new_startdate, new_enddate)
1008
1009 else:
1010
1011 if not (int(cur_event['enddate']) < datefrom or int(cur_event['startdate']) > dateto):
1012 events[e_id] = cur_event.copy()
1013 insertcalevents(cal_events, datefrom, dateto, e_id, cur_event['startdate'], cur_event['enddate'])
1014
1015 # cache update
1016 if not nocache:
1017 cache_filteredevents.update(pickle.dumps(events, PICKLE_PROTOCOL))
1018 cache_calevents.update(pickle.dumps(cal_events, PICKLE_PROTOCOL))
1019
1020 else:
1021 events = raw_events
1022
1023
1024 # sort cal_events
1025 # store event list into global variables in order to sort them
1026 Globs.events = events
1027
1028 for eachdate in cal_events.keys():
1029 cal_events[eachdate].sort(comp_cal_events)
1030
1031 debug(u'Total %d of events are loaded finally.' % len(events))
1032
1033 #debug('Events:')
1034 #for key in events.keys():
1035 # debug('__ %s' % events[key])
1036
1037 return events, cal_events
1038
1039
1040
1041 def loadEventsFromWikiPages():
1042
1043 events = {}
1044
1045 eventrecord_list = []
1046 eventpages = []
1047
1048 request = Globs.request
1049 category = Params.category
1050
1051 # cache configurations
1052 arena = Page(request, Globs.pagename)
1053 eventkey = 'events'
1054 pagelistkey = 'eventpages'
1055
1056 cache_events = caching.CacheEntry(request, arena, eventkey)
1057 cache_pages = caching.CacheEntry(request, arena, pagelistkey)
1058
1059
1060 # page list cache
1061
1062 debug('Checking page list cache')
1063
1064 # check the time at which page list cache has been created
1065
1066 cp_mtime = cache_pages.mtime()
1067 timedelta_days = 9999
1068
1069 if cp_mtime:
1070 cp_date = datetime.datetime.fromtimestamp(cp_mtime)
1071 today = datetime.datetime.fromtimestamp(time.time())
1072 datediff = today - cp_date
1073 timedelta_days = datediff.days
1074 debug('Time from page list cache built = %s' % datediff)
1075
1076
1077 if Globs.page_action == 'refresh' or cache_pages.needsUpdate(arena._text_filename()) or timedelta_days >= 1:
1078 categorypages = searchPages(request, category)
1079 for page in categorypages:
1080 eventpages.append(page.page_name)
1081 cache_pages.update('\n'.join(eventpages), True)
1082 debug('New page list is built: %d pages' % len(eventpages))
1083 else:
1084 eventpages = cache_pages.content(True).split('\n')
1085 debug('Cached page list is used: %d pages' % len(eventpages))
1086
1087
1088 # generating events
1089
1090 e_num = 0
1091 dirty = 0
1092 debug_records = {}
1093
1094 # fetch event records from each page in the category
1095 for page_name in eventpages:
1096
1097 p = Page(request, page_name)
1098 e_ref = page_name
1099
1100 eventrecordkey = 'eventrecords'
1101 cache_eventrecords = caching.CacheEntry(request, p, eventrecordkey)
1102
1103 if cache_eventrecords.needsUpdate(p._text_filename()) or Globs.page_action == 'refresh':
1104 dirty = 1
1105 page_content = p.get_raw_body()
1106 eventrecords, e_num = getEventRecordFromPage(page_content, e_ref, e_num)
1107 debug_records[e_ref] = '%d eventrecords are fetched from %s' % (len(eventrecords), e_ref)
1108 cache_eventrecords.update(pickle.dumps(eventrecords, PICKLE_PROTOCOL))
1109 else:
1110 try:
1111 eventrecords = pickle.loads(cache_eventrecords.content())
1112 debug_records[e_ref] = '%d cached eventrecords are used from %s' % (len(eventrecords), e_ref)
1113 except (pickle.UnpicklingError, IOError, EOFError, ValueError):
1114 dirty = 1
1115 page_content = p.get_raw_body()
1116 eventrecords, e_num = getEventRecordFromPage(page_content, e_ref, e_num)
1117 debug_records[e_ref] = '%d eventrecords are fetched from %s due to pickle error' % (len(eventrecords), e_ref)
1118 cache_eventrecords.update(pickle.dumps(eventrecords, PICKLE_PROTOCOL))
1119
1120 eventrecord_list.append(eventrecords)
1121
1122 # if no dirty, just fetch the cache
1123 if not (dirty or Globs.page_action == 'refresh'):
1124
1125 debug('Checking event cache: still valid')
1126
1127 try:
1128 events = pickle.loads(cache_events.content())
1129 debug('Cached event information is used: total %d events' % len(events))
1130 except (pickle.UnpicklingError, IOError, EOFError, ValueError):
1131 debug('Picke error at fetching cached events')
1132 events = {}
1133
1134 else:
1135
1136 debug('Checking event cache: it\'s dirty or requested to refresh')
1137
1138 # if there is no events (if it needs refreshed), generate events dictionary
1139 if not len(events.keys()):
1140
1141 # XXX: just debugging
1142 debug('Bulding new event information')
1143 for page_name in eventpages:
1144 debug(debug_records[page_name])
1145
1146
1147 day_delta = datetime.timedelta(days=1)
1148
1149 for eventrecords in eventrecord_list:
1150
1151 for evtrecord in eventrecords:
1152
1153 e_id = evtrecord['id']
1154
1155 # generating events
1156 events[e_id] = evtrecord
1157 #debug('event %s: %s' % (evtrecord['id'], evtrecord))
1158
1159 # after generating updated events, update the cache
1160 cache_events.update(pickle.dumps(events, PICKLE_PROTOCOL))
1161
1162 debug('Event information is newly built: total %d events' % len(events))
1163
1164 # end of updating events block
1165
1166
1167 return events
1168
1169
1170
1171 def getEventRecordFromPage(pagecontent, referpage, e_num):
1172
1173 request = Globs.request
1174
1175 eventrecords = []
1176 page_bgcolor = ''
1177 page_description = ''
1178
1179 # fetch the page default bgcolor
1180 regex_page_bgcolor = r"""
1181 ^\s+default_bgcolor::\s*
1182 (?P<pagebgcolor>\#[0-9a-fA-F]{6})
1183 \s*
1184 $
1185 """
1186
1187 pattern = re.compile(regex_page_bgcolor, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1188 match = pattern.search(pagecontent)
1189
1190 if match:
1191 page_bgcolor = match.group('pagebgcolor')
1192
1193 # fetch the page default description
1194 regex_page_description = r"""
1195 ^\s+default_description::\s*
1196 (?P<pagedescription>.*?)
1197 $
1198 """
1199
1200 pattern = re.compile(regex_page_description, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1201 match = pattern.search(pagecontent)
1202
1203 if match:
1204 page_description = match.group('pagedescription')
1205
1206
1207 # fetch event item
1208 regex_eventitem = r"""
1209 (?P<eventitem>
1210 (?P<heading>^\s*(?P<hmarker>=+)\s(?P<eventtitle>.*?)\s(?P=hmarker) $)
1211 (?P<eventdetail>.*?
1212 (?=
1213 ^\s*(?P<nexthmarker>=+)\s(?P<nexteventtitle>.*?)\s(?P=nexthmarker) $
1214 | \Z
1215 )
1216 )
1217 )
1218 """
1219
1220 pattern = re.compile(regex_eventitem, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1221 match = pattern.findall(pagecontent)
1222
1223 if match:
1224
1225 for matchitem in match:
1226
1227 eventitem = {}
1228
1229 eventtitle = matchitem[3]
1230 eventdetail = matchitem[4]
1231
1232 try:
1233 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)
1234 except (TypeError, ValueError):
1235 #debug('An event data is corrupted: invalid event format')
1236 continue
1237
1238 # set default values
1239 if not e_bgcolor:
1240 e_bgcolor = page_bgcolor
1241
1242 if not e_description:
1243 e_description = page_description
1244
1245 e_num += 1
1246 e_id = 'e%d' % e_num
1247
1248 eventitem['id'] = e_id
1249 eventitem['title'] = eventtitle
1250 eventitem['startdate'] = e_start_date
1251 eventitem['starttime'] = e_start_time
1252 eventitem['enddate'] = e_end_date
1253 eventitem['endtime'] = e_end_time
1254 eventitem['title'] = eventtitle
1255 eventitem['refer'] = referpage
1256 eventitem['bgcolor'] = e_bgcolor
1257 eventitem['description'] = e_description
1258 eventitem['recur_freq'] = e_recur_freq
1259 eventitem['recur_type'] = e_recur_type
1260 eventitem['recur_until'] = e_recur_until
1261
1262 eventitem['date_len'] = diffday(e_start_date, e_end_date) + 1
1263 eventitem['clone'] = 0
1264 eventitem['hid'] = getheadingid(request, referpage, eventtitle)
1265
1266 eventrecords.append(eventitem)
1267
1268 #debug('matched records: %d' % len(match))
1269
1270 return eventrecords, e_num
1271
1272
1273
1274 def geteventfield(detail):
1275
1276 regex_startdate = r"""
1277 ^\s+start::\s*
1278 (?P<startdate>\d{4}[/-]\d{2}[/-]\d{2})
1279 \s*
1280 (?P<starttime>\d{2}[:]\d{2})*
1281 \s*
1282 $
1283 """
1284
1285 regex_enddate = r"""
1286 ^\s+end::\s*
1287 (?P<enddate>\d{4}[/-]\d{2}[/-]\d{2})*
1288 \s*
1289 (?P<endtime>\d{2}[:]\d{2})*
1290 \s*
1291 $
1292 """
1293
1294 regex_bgcolor = r"""
1295 ^\s+bgcolor::\s*
1296 (?P<bgcolor>\#[0-9a-fA-F]{6})
1297 \s*
1298 $
1299 """
1300
1301 regex_description = r"""
1302 ^\s+description::\s*
1303 (?P<description>.*?)
1304 $
1305 """
1306
1307 regex_recur = r"""
1308 ^\s+recur::\s*
1309 (?P<recur_freq>\d+)
1310 \s*
1311 (?P<recur_type>day|week|weekday|month|year)
1312 \s*
1313 (
1314 until
1315 \s*
1316 (?P<recur_until>\d{4}[/-]\d{2}[/-]\d{2})
1317 )*
1318 $
1319 """
1320
1321 # need help on regular expressions for more efficient/flexible form
1322
1323 # compile regular expression objects
1324
1325 pattern_startdate = re.compile(regex_startdate, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1326 pattern_enddate = re.compile(regex_enddate, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1327 pattern_bgcolor = re.compile(regex_bgcolor, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1328 pattern_description = re.compile(regex_description, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1329 pattern_recur = re.compile(regex_recur, re.UNICODE + re.MULTILINE + re.IGNORECASE + re.DOTALL + re.VERBOSE)
1330
1331 ##################### retrieve startdate
1332 match = pattern_startdate.search(detail)
1333
1334 if match:
1335 startdate = match.group('startdate')
1336 starttime = match.group('starttime')
1337 else:
1338 startdate = ''
1339 starttime = ''
1340
1341 ##################### retrieve enddate
1342 match = pattern_enddate.search(detail)
1343
1344 if match:
1345 enddate = match.group('enddate')
1346 endtime = match.group('endtime')
1347 else:
1348 enddate = ''
1349 endtime = ''
1350
1351 ##################### retrieve bgcolor
1352 match = pattern_bgcolor.search(detail)
1353
1354 if match:
1355 bgcolor = match.group('bgcolor')
1356 else:
1357 bgcolor = ''
1358
1359 ##################### retrieve description
1360 match = pattern_description.search(detail)
1361
1362 if match:
1363 description = match.group('description')
1364 else:
1365 description = ''
1366
1367 ##################### retrieve recurrence
1368 match = pattern_recur.search(detail)
1369
1370 if match:
1371 recur_freq = int(match.group('recur_freq'))
1372 recur_type = match.group('recur_type')
1373 recur_until = match.group('recur_until')
1374
1375 else:
1376 recur_freq = 0
1377 recur_type = ''
1378 recur_until = ''
1379
1380
1381 # check validity of each fields
1382
1383 if not startdate:
1384 #debug('start date is not specified')
1385 # self.printoutput('Parse Error', msg, '')
1386 # ERROR
1387 return '','','','','','','','','',''
1388
1389 if (starttime or endtime) and not (starttime and endtime):
1390 #debug('no or 2 time field should be specified')
1391 # ERROR
1392 return '','','','','','','','','',''
1393
1394 # if no time, it's 1-day event
1395 if not enddate:
1396 enddate = startdate
1397
1398 try:
1399 syear, smonth, sday = getdatefield(startdate)
1400 eyear, emonth, eday = getdatefield(enddate)
1401 except (TypeError, ValueError):
1402 #debug('invalid date format: %s, %s' % (startdate, enddate))
1403 return '','','','','','','','','',''
1404
1405 if datetime.date(syear, smonth, sday) > datetime.date(eyear, emonth, eday):
1406 #debug('startdate should precede enddate')
1407 return '','','','','','','','','',''
1408
1409 # format date
1410 startdate = formatDate(syear, smonth, sday)
1411 enddate = formatDate(eyear, emonth, eday)
1412
1413 if (starttime and endtime):
1414 try:
1415 shour, smin = gettimefield(starttime)
1416 ehour, emin = gettimefield(endtime)
1417 except (TypeError, ValueError):
1418 #debug('invalid time format: %s, %s' % (startdate, enddate))
1419 return '','','','','','','','','',''
1420
1421 if startdate == enddate:
1422 if datetime.time(shour, smin) > datetime.time(ehour, emin):
1423 #debug('starttime should precede endtime')
1424 return '','','','','','','','','',''
1425
1426 # format time
1427 starttime = u'%02d%02d' %(shour, smin)
1428 endtime = u'%02d%02d' %(ehour, emin)
1429
1430 # check recurrent data
1431 event_len = diffday(startdate, enddate)
1432 if recur_freq:
1433
1434 if recur_type == 'day':
1435 if event_len > int(recur_freq):
1436 debug('event length should be smaller than recurrence interval')
1437 return '','','','','','','','','',''
1438
1439 elif recur_type == 'week':
1440 if event_len > int(recur_freq) * 7:
1441 debug('event length should be smaller than recurrence interval')
1442 return '','','','','','','','','',''
1443
1444 elif recur_type == 'weekday':
1445 if event_len > 25:
1446 debug('event length should be smaller than recurrence interval')
1447 return '','','','','','','','','',''
1448
1449 elif recur_type == 'month':
1450 if event_len > int(recur_freq) * 25:
1451 debug('event length should be smaller than recurrence interval')
1452 return '','','','','','','','','',''
1453
1454 elif recur_type == 'year':
1455 if event_len > int(recur_freq) * 365:
1456 debug('event length should be smaller than recurrence interval')
1457 return '','','','','','','','','',''
1458
1459 if recur_until:
1460 try:
1461 ryear, rmonth, rday = getdatefield(recur_until)
1462 except (TypeError, ValueError):
1463 debug('invalid date format: %s' % recur_until)
1464 return '','','','','','','','','',''
1465
1466 recur_until = formatDate(ryear, rmonth, rday)
1467
1468 if int(recur_until) < int(enddate):
1469 debug('recur_until should precede enddate')
1470 return '','','','','','','','','',''
1471
1472 return startdate, starttime, enddate, endtime, bgcolor, description, recur_freq, recur_type, recur_until
1473
1474
1475
1476 def converttext(targettext):
1477 # Converts some special characters of html to plain-text style
1478 # What else to handle?
1479
1480 targettext = targettext.replace(u'&', '&')
1481 targettext = targettext.replace(u'>', '>')
1482 targettext = targettext.replace(u'<', '<')
1483 targettext = targettext.replace(u'\n', '<br>')
1484 targettext = targettext.replace(u'"', '"')
1485 targettext = targettext.replace(u'\t', '  ')
1486 targettext = targettext.replace(u' ', ' ')
1487
1488 return targettext
1489
1490
1491 # monthly view
1492 def showeventcalendar(year, month):
1493
1494 debug('Show Calendar: Monthly View')
1495
1496 request = Globs.request
1497 formatter = Globs.formatter
1498 _ = request.getText
1499
1500 wkend = Globs.wkend
1501 months= Globs.months
1502 wkdays = Globs.wkdays
1503
1504 # get the calendar
1505 monthcal = calendar.monthcalendar(year, month)
1506
1507 # shows current year & month
1508 html_header_curyearmonth = calhead_yearmonth(year, month, 'head_yearmonth')
1509
1510 r7 = range(7)
1511
1512 # shows header of week days
1513 html_header_weekdays = []
1514
1515 for wkday in r7:
1516 wday = _(wkdays[wkday])
1517 html_header_weekdays.append( calhead_weekday(wday, 'head_weekday') )
1518 html_header_weekdays = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays)
1519
1520 # pending events for next row
1521 next_pending = []
1522
1523 # gets previous, next month
1524 day_delta = datetime.timedelta(days=-1)
1525 cur_month = datetime.date(year, month, 1)
1526 prev_month = cur_month + day_delta
1527
1528 day_delta = datetime.timedelta(days=15)
1529 cur_month_end = datetime.date(year, month, 25)
1530 next_month = cur_month_end + day_delta
1531
1532 prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month)
1533 next_monthcal = calendar.monthcalendar(next_month.year, next_month.month)
1534
1535 # shows days
1536 html_week_rows = []
1537
1538 # set ranges of events
1539 datefrom = u'%04d%02d21' % (prev_month.year, prev_month.month)
1540 dateto = u'%04d%02d06' % (next_month.year, next_month.month)
1541
1542 # read all the events
1543 events, cal_events = loadEvents(datefrom, dateto)
1544
1545 #debug(u' events: %s' % events)
1546 #debug(u' cal_events: %s' % cal_events)
1547
1548 for week in monthcal:
1549
1550 # day head rows
1551 html_headday_cols = []
1552 html_events_rows = []
1553
1554 for wkday in r7:
1555
1556 day = week[wkday]
1557
1558 if not day:
1559 if week == monthcal[0]:
1560 nb_day = prev_monthcal[-1][wkday]
1561 else:
1562 nb_day = next_monthcal[0][wkday]
1563
1564 html_headday_cols.append( calhead_day_nbmonth(nb_day) )
1565 else:
1566 html_headday_cols.append( calhead_day(year, month, day, wkday) )
1567
1568 html_headday_row = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols)
1569 html_week_rows.append(html_headday_row)
1570
1571 # dummy rows
1572 html_headdummy_cols = []
1573
1574 for wkday in r7:
1575 day = week[wkday]
1576 if not day:
1577 html_headdummy_cols.append( calshow_blankbox('head_dummy_nbmonth') )
1578 else:
1579 html_headdummy_cols.append( calshow_blankbox('head_dummy') )
1580
1581 html_headdummy_cols = u'\r\n'.join(html_headdummy_cols)
1582 html_week_rows.append(' <tr>\r\n%s </tr>\r\n' % html_headdummy_cols)
1583
1584 # pending events for next row
1585 pending = next_pending
1586 next_pending = []
1587
1588 # show events
1589 while 1:
1590 event_left = 7
1591 colspan = -1
1592 html_events_cols = []
1593
1594 for wkday in r7:
1595
1596 day = week[wkday]
1597
1598 if not day:
1599 if week == monthcal[0]:
1600 cur_date = formatDate(prev_month.year, prev_month.month, prev_monthcal[-1][wkday])
1601 else:
1602 cur_date = formatDate(next_month.year, next_month.month, next_monthcal[0][wkday])
1603 else:
1604 cur_date = formatDate(year, month, day)
1605
1606 # if an event is already displayed with colspan
1607 if colspan > 0:
1608 colspan -= 1
1609 if cal_events.has_key(cur_date) and lastevent in cal_events[cur_date]:
1610 cal_events[cur_date].remove(lastevent)
1611
1612 continue
1613
1614 # if there is any event for this date
1615 if cal_events.has_key(cur_date):
1616 if len(cal_events[cur_date]) > 0:
1617
1618 # if there is any pending event in the previous week
1619 if wkday == 0 and len(pending) > 0:
1620 todo_event_id = pending.pop(0)
1621 if todo_event_id in cal_events[cur_date]:
1622 cur_event = events[todo_event_id]
1623 temp_len = diffday(cur_date, cur_event['enddate']) + 1
1624
1625 # calculate colspan value
1626 if (7-wkday) < temp_len:
1627 colspan = 7 - wkday
1628 next_pending.append(cur_event['id'])
1629 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) )
1630
1631 else:
1632 colspan = temp_len
1633 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) )
1634
1635
1636 cal_events[cur_date].remove(todo_event_id)
1637
1638 colspan -= 1
1639 lastevent = todo_event_id
1640 else:
1641 debug('Warning: no such event in cal_events')
1642
1643 continue
1644
1645 # if there is no pending event in the previous week, start a new event
1646 event_found = 0
1647 for e_id in cal_events[cur_date]:
1648
1649 # if the start date of the event is current date
1650 if events[e_id]['startdate'] == cur_date:
1651
1652 cur_event = events[cal_events[cur_date].pop(cal_events[cur_date].index(e_id))]
1653
1654 # calculate colspan value
1655 if (7-wkday) < cur_event['date_len']:
1656 colspan = 7 - wkday
1657 next_pending.append(cur_event['id'])
1658 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'pending', cur_date) )
1659
1660 else:
1661 colspan = cur_event['date_len']
1662 html_events_cols.append( calshow_eventbox(cur_event, colspan, '', cur_date) )
1663
1664 colspan -= 1
1665 lastevent = cur_event['id']
1666 event_found = 1
1667 break
1668
1669 # if the start date of the event is NOT current date
1670 else:
1671
1672 # pending event from previous month
1673 if wkday == 0 and week == monthcal[0]:
1674
1675 cur_event = events[cal_events[cur_date].pop(0)]
1676 temp_len = diffday(cur_date, cur_event['enddate']) + 1
1677
1678 # calculate colspan value
1679 if (7-wkday) < temp_len:
1680 colspan = 7 - wkday
1681 next_pending.append(cur_event['id'])
1682 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append_pending', cur_date) )
1683 else:
1684 colspan = temp_len
1685 html_events_cols.append( calshow_eventbox(cur_event, colspan, 'append', cur_date) )
1686
1687 colspan -= 1
1688 lastevent = cur_event['id']
1689 event_found = 1
1690 break
1691
1692 # if there is no event to start
1693 if not event_found:
1694 if not day:
1695 html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1696 else:
1697 html_events_cols.append( calshow_blankbox('cal_noevent') )
1698 event_left -= 1
1699
1700 else:
1701 if not day:
1702 html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1703 else:
1704 html_events_cols.append( calshow_blankbox('cal_noevent') )
1705
1706 event_left -= 1
1707
1708 # if there is NO event for this date
1709 else:
1710 if not day:
1711 html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1712 else:
1713 html_events_cols.append( calshow_blankbox('cal_noevent') )
1714
1715 event_left -= 1
1716
1717 # if no event for this entry
1718 if not event_left:
1719 # ignore the previous entry
1720 break
1721 else:
1722 html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1723
1724 # show dummy blank slots for week height
1725 left_blank_rows = 2 - len(html_events_rows)
1726
1727 # remove the followings
1728 if left_blank_rows > 0 and 0:
1729 for i in range(left_blank_rows):
1730 html_events_cols = []
1731 for wkday in r7:
1732 day = week[wkday]
1733 if not day:
1734 html_events_cols.append( calshow_blankbox('cal_nbmonth') )
1735 else:
1736 html_events_cols.append( calshow_blankbox('cal_noevent') )
1737
1738 html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1739
1740
1741 # close the week slots
1742 html_events_cols = []
1743 for wkday in r7:
1744 day = week[wkday]
1745 if not day:
1746 html_events_cols.append( calshow_blankbox('cal_last_nbmonth') )
1747 else:
1748 html_events_cols.append( calshow_blankbox('cal_last_noevent') )
1749
1750 html_events_rows.append(' <tr>\r\n%s </tr>\r\n' % u'\r\n'.join(html_events_cols))
1751
1752 html_events_rows = u'\r\n'.join(html_events_rows)
1753 html_week_rows.append(html_events_rows)
1754
1755 html_calendar_rows = u'\r\n'.join(html_week_rows)
1756
1757 html_cal_table = [
1758 u'\r\n<div id="eventcalendar">',
1759 u'<table class="eventcalendar" %s>' % Params.monthlywidth,
1760 u'%s' % html_header_curyearmonth,
1761 u'%s' % html_header_weekdays,
1762 u'%s' % html_calendar_rows,
1763 u'</table>',
1764 u'</div>',
1765 ]
1766 html_cal_table = u'\r\n'.join(html_cal_table)
1767
1768 return html_cal_table
1769
1770 # simple view
1771 def showsimpleeventcalendar(year, month):
1772
1773 debug('Show Calendar: Simple View')
1774
1775 request = Globs.request
1776 formatter = Globs.formatter
1777 _ = request.getText
1778
1779 wkend = Globs.wkend
1780 months= Globs.months
1781 wkdays = Globs.wkdays
1782
1783 # get the calendar
1784 monthcal = calendar.monthcalendar(year, month)
1785
1786 # shows current year & month
1787 html_header_curyearmonth = calhead_yearmonth(year, month, 'simple_yearmonth')
1788
1789 r7 = range(7)
1790
1791 # shows header of week days
1792 html_header_weekdays = []
1793
1794 for wkday in r7:
1795 wday = wkdays[wkday]
1796 html_header_weekdays.append( calhead_weekday(wday, 'simple_weekday') )
1797 html_header_weekdays = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_header_weekdays)
1798
1799 # gets previous, next month
1800 day_delta = datetime.timedelta(days=-1)
1801 cur_month = datetime.date(year, month, 1)
1802 prev_month = cur_month + day_delta
1803
1804 day_delta = datetime.timedelta(days=15)
1805 cur_month_end = datetime.date(year, month, 25)
1806 next_month = cur_month_end + day_delta
1807
1808 prev_monthcal = calendar.monthcalendar(prev_month.year, prev_month.month)
1809 next_monthcal = calendar.monthcalendar(next_month.year, next_month.month)
1810
1811 # shows days
1812 html_week_rows = []
1813
1814 # set ranges of events
1815 datefrom = u'%04d%02d21' % (prev_month.year, prev_month.month)
1816 dateto = u'%04d%02d06' % (next_month.year, next_month.month)
1817
1818 # read all the events
1819 events, cal_events = loadEvents(datefrom, dateto)
1820
1821 for week in monthcal:
1822
1823 # day head rows
1824 html_headday_cols = []
1825 html_events_rows = []
1826
1827 for wkday in r7:
1828
1829 day = week[wkday]
1830
1831 if not day:
1832 if week == monthcal[0]:
1833 nb_day = prev_monthcal[-1][wkday]
1834 else:
1835 nb_day = next_monthcal[0][wkday]
1836
1837 html_headday_cols.append( simple_eventbox(year, month, day, nb_day, 'simple_nb') )
1838 else:
1839 cur_date = formatDate(year, month, day)
1840 if cal_events.has_key(cur_date):
1841 html_headday_cols.append( simple_eventbox(year, month, day, wkday, 'simple_event') )
1842 else:
1843 html_headday_cols.append( simple_eventbox(year, month, day, wkday, 'simple_noevent') )
1844
1845 html_headday_row = ' <tr>\r\n%s\r\n</tr>\r\n' % u'\r\n'.join(html_headday_cols)
1846 html_week_rows.append(html_headday_row)
1847
1848 html_calendar_rows = u'\r\n'.join(html_week_rows)
1849
1850 html_cal_table = [
1851 u'\r\n<div id="eventcalendar">',
1852 u'<table class="simplecalendar" %s>' % Params.simplewidth,
1853 u'%s' % html_header_curyearmonth,
1854 u'%s' % html_header_weekdays,
1855 u'%s' % html_calendar_rows,
1856 u'</table>',
1857 u'</div>',
1858 ]
1859 html_cal_table = u'\r\n'.join(html_cal_table)
1860
1861 return html_cal_table
1862
1863
1864 # show weekday
1865 def calhead_yearmonth(year, month, headclass):
1866
1867 months = Globs.months
1868 monthstyle_us = Globs.month_style_us
1869 cal_action = Globs.cal_action
1870 page_name = Globs.pagename
1871
1872 nextyear, nextmonth = yearmonthplusoffset(year, month, 1)
1873 prevyear, prevmonth = yearmonthplusoffset(year, month, -1)
1874
1875 prevlink = u'%s?calaction=%s&caldate=%d%02d' % (page_name, cal_action, prevyear, prevmonth)
1876 nextlink = u'%s?calaction=%s&caldate=%d%02d' % (page_name, cal_action, nextyear, nextmonth)
1877 curlink = u'%s?calaction=%s&caldate=%d%02d' % (page_name, cal_action, year, month)
1878
1879 if monthstyle_us:
1880 stryearmonth = u'%s %d' % (months[month-1], year)
1881 strnextmonth = u'%s %d' % (months[nextmonth-1], nextyear)
1882 strprevmonth = u'%s %d' % (months[prevmonth-1], prevyear)
1883 else:
1884 stryearmonth = u'%d / %02d' % (year, month)
1885 strnextmonth = u'%d / %02d' % (nextyear, nextmonth)
1886 strprevmonth = u'%d / %02d' % (prevyear, prevmonth)
1887
1888 html = [
1889 u' <tr>',
1890 u' <td class="%s"><a href="%s" title="%s"><</a></td>' % (headclass, prevlink, strprevmonth),
1891 u' <td colspan="5" class="%s"><a href="%s" title="Refresh">%s</a></td>' % (headclass, curlink, stryearmonth),
1892 u' <td class="%s"><a href="%s" title="%s">></a></td>' % (headclass, nextlink, strnextmonth),
1893 u' </tr>',
1894 ]
1895
1896 return u'\r\n'.join(html)
1897
1898 # show days in simple
1899 def simple_eventbox(year, month, day, wkday, boxclass):
1900 wkend = Globs.wkend
1901 if wkday == wkend:
1902 html_text = u'<font color="#aa7744">%s</font>' % day
1903 else:
1904 html_text = u'%s' % day
1905
1906 cyear, cmonth, cday = gettodaydate()
1907
1908 if boxclass == 'simple_nb':
1909 html = u' <td class="%s"> </td>\r\n' % boxclass
1910 else:
1911 if cyear == year and cmonth == month and cday == day:
1912 html = u' <td class="%s_today">%s</td>\r\n' % (boxclass, html_text)
1913 else:
1914 html = u' <td class="%s">%s</td>\r\n' % (boxclass, html_text)
1915
1916 return html
1917
1918
1919 # show weekday
1920 def calhead_weekday(wday, headclass):
1921 if headclass == 'simple_weekday':
1922 html = u' <td class="%s">%s</td>\r\n' % (headclass, wday[0])
1923 else:
1924 html = u' <td class="%s">%s</td>\r\n' % (headclass, wday)
1925
1926 return html
1927
1928
1929 # show days of current month
1930 def calhead_day(year, month, day, wkday):
1931 wkend = Globs.wkend
1932 if wkday == wkend:
1933 html_text = u'<font color="#FF3300">%s</font>' % day
1934 else:
1935 html_text = u'%s' % day
1936
1937 cyear, cmonth, cday = gettodaydate()
1938
1939 if cyear == year and cmonth == month and cday == day:
1940 html = u' <td class="head_day_today"> %s</td>\r\n' % html_text
1941 else:
1942 html = u' <td class="head_day"> %s</td>\r\n' % html_text
1943
1944 return html
1945
1946
1947 # show days of previous or next month
1948 def calhead_day_nbmonth(day):
1949 html = u' <td class="head_day_nbmonth"> %s</td>\r\n' % day
1950 return html
1951
1952
1953 # show blank calendar box
1954 def calshow_blankbox(classname):
1955 html = u' <td class="%s"> </td>' % classname
1956 return html
1957
1958 # show eventbox
1959 def calshow_eventbox(event, colspan, status, cur_date):
1960 if status:
1961 status = u'_%s' % status
1962
1963 title = event['title']
1964 eid = event['id']
1965 startdate = event['startdate']
1966 enddate = event['enddate']
1967 starttime = event['starttime']
1968 endtime = event['endtime']
1969 description = event['description']
1970 bgcolor = event['bgcolor']
1971
1972 year, month, day = getdatefield(cur_date)
1973
1974 if bgcolor:
1975 bgcolor = 'background-color: %s;' % bgcolor
1976 else:
1977 bgcolor = 'background-color: %s;' % Params.bgcolor
1978
1979 if (startdate == enddate) and starttime:
1980 shour, smin = gettimefield(starttime)
1981
1982 link = [
1983 u'<table width="100%%" style="border-width: 0px; padding: 0px; margin: 0px;"><tr>\r\n',
1984 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),
1985 u'<td style="border-width: 0px; padding: 0px; margin: 0px; text-align: left; vertical-align: top;font-size: 8pt;">',
1986 u'%s' % showReferPageParsed(event, 'title', 1),
1987 u'</td>\r\n</tr></table>',
1988 ]
1989 link = u''.join(link)
1990 else:
1991 link = u'%s' % showReferPageParsed(event, 'title', 1)
1992
1993
1994 html = [
1995 u' <td class="cal_eventbox" colspan="%d"><table class="cal_event">' % colspan,
1996 u' <tr><td id="cal_event_%s" class="cal_event%s" style="%s">%s</td></tr>' % (eid, status, bgcolor, link),
1997 u' </table></td>',
1998 ]
1999
2000 return u'\r\n'.join(html)
2001
2002
2003 def insertcalevents(cal_events, datefrom, dateto, e_id, e_start_date, e_end_date):
2004
2005
2006 if not (int(e_start_date) > dateto or int(e_end_date) < datefrom):
2007
2008 e_start_date = str(max(int(e_start_date), datefrom))
2009 e_end_date = str(min(int(e_end_date), dateto))
2010
2011 day_delta = datetime.timedelta(days=1)
2012 e_start_year, e_start_month, e_start_day = getdatefield(e_start_date)
2013 cur_datetime = datetime.date(e_start_year, e_start_month, e_start_day)
2014
2015 while 1:
2016 tmp_record_date = formatdateobject(cur_datetime)
2017
2018 if not cal_events.has_key(tmp_record_date):
2019 cal_events[tmp_record_date] = []
2020 cal_events[tmp_record_date].append(e_id)
2021
2022 if tmp_record_date == e_end_date:
2023 break
2024
2025 cur_datetime = cur_datetime + day_delta
2026
2027
2028 # date format should be like '20051004' for 2005, Oct., 04
2029 def diffday(date1, date2):
2030
2031 try:
2032 year1, month1, day1 = getdatefield(date1)
2033 year2, month2, day2 = getdatefield(date2)
2034 tmp_diff = datetime.date(year2, month2, day2) - datetime.date(year1, month1, day1)
2035 except (TypeError, ValueError):
2036 debug('An event data is corrupted: invalid date format')
2037 return 0
2038
2039 return tmp_diff.days
2040
2041
2042 def formatDate(year, month, day):
2043 # returns like: '20051004'
2044 return u'%4d%02d%02d' % (year, month, day)
2045
2046 def formatdateobject(obj_date):
2047
2048 return formatDate(obj_date.year, obj_date.month, obj_date.day)
2049
2050
2051 def cliprgb(r,g,b): # don't use 255!
2052 if r < 0: r=0
2053 if r > 254: r=254
2054 if b < 0: b=0
2055 if b > 254: b=254
2056 if g < 0: g=0
2057 if g > 254: g=254
2058 return r, g, b
2059
2060
2061 def debug(astring):
2062 Globs.debugmsg += u'<li>%s\n' % astring
2063
2064
2065 def yearmonthplusoffset(year, month, offset):
2066 month = month+offset
2067 # handle offset and under/overflows - quick and dirty, yes!
2068 while month < 1:
2069 month = month + 12
2070 year = year - 1
2071 while month > 12:
2072 month = month - 12
2073 year = year + 1
2074 return year, month
2075
2076
2077 def searchPages(request, needle):
2078 # Search the pages and return the results
2079 query = search.QueryParser().parse_query(needle)
2080 results = search.searchPages(request, query)
2081 #results.sortByPagename()
2082
2083 return results.hits
2084
2085 html = []
2086 for page in results.hits:
2087 html.append(page.page_name)
2088
2089 html = u',<br>'.join(html)
2090 return u'%s<p>%s' % (Params.category, html)
2091
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.