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