1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - EventAggregatorSummary Action 4 5 @copyright: 2008, 2009 by Paul Boddie <paul@boddie.org.uk> 6 @copyright: 2000-2004 Juergen Hermann <jh@web.de>, 7 2003-2008 MoinMoin:ThomasWaldmann, 8 2004-2006 MoinMoin:AlexanderSchremmer, 9 2007 MoinMoin:ReimarBauer. 10 @license: GNU GPL (v2 or later), see COPYING.txt for details. 11 """ 12 13 from MoinMoin.action import ActionBase 14 from MoinMoin import config 15 from MoinMoin.Page import Page 16 import MoinMoin.util # for MoinMoin 1.5.x 17 from MoinMoin import wikiutil 18 import EventAggregatorSupport 19 20 Dependencies = ['pages'] 21 22 # Action class and supporting functions. 23 24 class EventAggregatorSummary(ActionBase): 25 26 "A summary dialogue requesting various parameters." 27 28 def get_form_html(self, buttons_html): 29 _ = self._ 30 request = self.request 31 32 category_list = [] 33 34 for category_name, category_pagename in \ 35 EventAggregatorSupport.getCategoryMapping( 36 EventAggregatorSupport.getCategories(request), 37 request): 38 39 category_list.append('<option value="%s">%s</option>' % (category_pagename, category_name)) 40 41 month_list = [] 42 month_list.append('<option value=""></option>') 43 44 for month in range(1, 13): 45 month_label = _(EventAggregatorSupport.getMonthLabel(month)) 46 month_list.append('<option value="%02d">%s</option>' % (month, month_label)) 47 48 year_label = [] 49 50 d = { 51 "buttons_html" : buttons_html, 52 "category_label" : _("Categories"), 53 "category_list" : "\n".join(category_list), 54 "month_list" : "\n".join(month_list), 55 "start_label" : _("Start year and month"), 56 "start_year_default" : "", 57 "end_label" : _("End year and month"), 58 "end_year_default" : "", 59 } 60 61 return ''' 62 <table> 63 <tr> 64 <td class="label"><label>%(category_label)s</label></td> 65 <td class="content"> 66 <select multiple="multiple" name="category"> 67 %(category_list)s 68 </select> 69 </td> 70 </tr> 71 <tr> 72 <td class="label"><label>%(start_label)s</label></td> 73 <td> 74 <select name="start-month"> 75 %(month_list)s 76 </select> 77 <input name="start-year" type="text" value="%(start_year_default)s" size="4" /> 78 </td> 79 </tr> 80 <tr> 81 <td class="label"><label>%(end_label)s</label></td> 82 <td> 83 <select name="end-month"> 84 %(month_list)s 85 </select> 86 <input name="end-year" type="text" value="%(end_year_default)s" size="4" /> 87 </td> 88 </tr> 89 <tr> 90 <td></td> 91 <td class="buttons"> 92 %(buttons_html)s 93 </td> 94 </tr> 95 </table> 96 ''' % d 97 98 def do_action(self): 99 100 "Write the iCalendar resource." 101 102 _ = self._ 103 form = self.request.form 104 105 # If no category names exist in the request, an error message is 106 # returned. 107 108 category_names = form.get("category", []) 109 110 if not category_names: 111 return 0, _("No categories specified.") 112 113 write_resource(self.request) 114 return 1, None 115 116 def render_success(self, msg, msgtype=None): 117 118 """ 119 Render neither 'msg' nor 'msgtype' since a resource has already been 120 produced. 121 NOTE: msgtype is optional because MoinMoin 1.5.x does not support it. 122 """ 123 124 pass 125 126 def getQuotedText(text): 127 128 "Return the 'text' quoted for iCalendar purposes." 129 130 return text.replace(";", r"\;").replace(",", r"\,") 131 132 def write_resource(request): 133 134 """ 135 For the given 'request', write an iCalendar summary of the event data found 136 in the categories specified via the "category" request parameter, using the 137 "start" and "end" parameters (if specified). Multiple "category" parameters 138 can be specified. 139 """ 140 141 category_names = request.form.get("category", []) 142 format = request.form.get("format", ["iCalendar"])[0] 143 144 # Otherwise, produce an iCalendar resource. 145 146 calendar_start = EventAggregatorSupport.getFormMonth(request, None, "start") 147 calendar_end = EventAggregatorSupport.getFormMonth(request, None, "end") 148 149 # Look for separate start and end years and months. 150 151 form = request.form 152 153 if calendar_start is None: 154 calendar_start = EventAggregatorSupport.getFormMonthPair(request, "start-year", "start-month") 155 156 if calendar_end is None: 157 calendar_end = EventAggregatorSupport.getFormMonthPair(request, "end-year", "end-month") 158 159 events, shown_events, all_shown_events, earliest, latest = \ 160 EventAggregatorSupport.getEvents(request, category_names, calendar_start, calendar_end) 161 162 latest_timestamp = EventAggregatorSupport.setEventTimestamps(request, all_shown_events) 163 164 # Output summary data... 165 166 if EventAggregatorSupport.isMoin15(): 167 send_headers = request.http_headers 168 else: 169 send_headers = request.emit_http_headers 170 171 # Define headers. 172 173 if format == "iCalendar": 174 headers = ["Content-Type: text/calendar; charset=%s" % config.charset] 175 elif format == "RSS": 176 headers = ["Content-Type: application/rss+xml; charset=%s" % config.charset] 177 178 # Define the last modified time. 179 180 if latest_timestamp is not None: 181 headers.append("Last-Modified: %s" % EventAggregatorSupport.getHTTPTimeString(latest_timestamp)) 182 183 send_headers(headers) 184 185 # iCalendar output... 186 187 if format == "iCalendar": 188 request.write("BEGIN:VCALENDAR\r\n") 189 request.write("PRODID:-//MoinMoin//EventAggregatorSummary\r\n") 190 request.write("VERSION:2.0\r\n") 191 192 for event_page, event_details in all_shown_events: 193 194 # Get the summary details. 195 196 event_summary = EventAggregatorSupport.getEventSummary(event_page, event_details) 197 link = EventAggregatorSupport.getPageURL(request, event_page) 198 199 # Output the event details. 200 201 request.write("BEGIN:VEVENT\r\n") 202 request.write("UID:%s\r\n" % link) 203 request.write("URL:%s\r\n" % link) 204 request.write("DTSTAMP:%04d%02d%02dT%02d%02d%02dZ\r\n" % event_details["created"][:6]) 205 request.write("LAST-MODIFIED:%04d%02d%02dT%02d%02d%02dZ\r\n" % event_details["last-modified"][:6]) 206 request.write("SEQUENCE:%d\r\n" % event_details["sequence"]) 207 request.write("DTSTART;VALUE=DATE:%04d%02d%02d\r\n" % event_details["start"]) 208 request.write("DTEND;VALUE=DATE:%04d%02d%02d\r\n" % EventAggregatorSupport.nextdate(event_details["end"])) 209 request.write("SUMMARY:%s\r\n" % getQuotedText(event_summary)) 210 211 # Optional details. 212 213 if event_details.has_key("topics") or event_details.has_key("categories"): 214 request.write("CATEGORIES:%s\r\n" % ",".join( 215 [getQuotedText(topic) for topic in event_details.get("topics") or event_details.get("categories")] 216 )) 217 if event_details.has_key("location"): 218 request.write("LOCATION:%s\r\n" % getQuotedText(event_details["location"])) 219 220 request.write("END:VEVENT\r\n") 221 222 request.write("END:VCALENDAR\r\n") 223 224 elif format == "RSS": 225 request.write('<rss version="2.0">\r\n') 226 request.write('<channel>\r\n') 227 request.write('<title>Events</title>\r\n') 228 request.write('<link>%s</link>\r\n' % request.getBaseURL()) 229 request.write('<description>Events published on %s</description>\r\n' % request.getBaseURL()) 230 request.write('<lastBuildDate>%s</lastBuildDate>\r\n' % EventAggregatorSupport.getHTTPTimeString(latest_timestamp)) 231 232 for event_page, event_details in all_shown_events: 233 234 # Get the summary details. 235 236 event_summary = EventAggregatorSupport.getEventSummary(event_page, event_details) 237 link = EventAggregatorSupport.getPageURL(request, event_page) 238 239 request.write('<item>\r\n') 240 request.write('<title>%s</title>\r\n' % wikiutil.escape(event_summary)) 241 request.write('<link>%s</link>\r\n' % link) 242 request.write('<description>%s</description>\r\n' % wikiutil.escape(event_details["last-comment"])) 243 244 for topic in event_details.get("topics") or event_details.get("categories") or []: 245 request.write('<category>%s</category>\r\n' % topic) 246 247 request.write('<pubDate>%s</pubDate>\r\n' % EventAggregatorSupport.getHTTPTimeString(event_details["created"])) 248 request.write('<guid>%s#%s</guid>\r\n' % (link, event_details["sequence"])) 249 request.write('</item>\r\n') 250 251 request.write('</channel>\r\n') 252 request.write('</rss>\r\n') 253 254 if EventAggregatorSupport.isMoin15(): 255 raise MoinMoin.util.MoinMoinNoFooter 256 257 # Action function. 258 259 def execute(pagename, request): 260 EventAggregatorSummary(pagename, request).render() 261 262 # vim: tabstop=4 expandtab shiftwidth=4