paul@10 | 1 | # -*- coding: iso-8859-1 -*- |
paul@10 | 2 | """ |
paul@10 | 3 | MoinMoin - EventAggregatorSummary Action |
paul@10 | 4 | |
paul@284 | 5 | @copyright: 2008, 2009, 2010, 2011, 2012 by Paul Boddie <paul@boddie.org.uk> |
paul@10 | 6 | @copyright: 2000-2004 Juergen Hermann <jh@web.de>, |
paul@24 | 7 | 2003-2008 MoinMoin:ThomasWaldmann, |
paul@24 | 8 | 2004-2006 MoinMoin:AlexanderSchremmer, |
paul@19 | 9 | 2007 MoinMoin:ReimarBauer. |
paul@60 | 10 | 2009 Cristian Rigamonti <rigamonti@fsfeurope.org> |
paul@10 | 11 | @license: GNU GPL (v2 or later), see COPYING.txt for details. |
paul@10 | 12 | """ |
paul@10 | 13 | |
paul@19 | 14 | from MoinMoin.action import ActionBase |
paul@10 | 15 | from MoinMoin import config |
paul@24 | 16 | from MoinMoin.Page import Page |
paul@29 | 17 | from MoinMoin import wikiutil |
paul@168 | 18 | from EventAggregatorSupport import * |
paul@137 | 19 | |
paul@10 | 20 | Dependencies = ['pages'] |
paul@10 | 21 | |
paul@19 | 22 | # Action class and supporting functions. |
paul@19 | 23 | |
paul@168 | 24 | class EventAggregatorSummary(ActionBase, ActionSupport): |
paul@19 | 25 | |
paul@19 | 26 | "A summary dialogue requesting various parameters." |
paul@19 | 27 | |
paul@19 | 28 | def get_form_html(self, buttons_html): |
paul@19 | 29 | _ = self._ |
paul@19 | 30 | request = self.request |
paul@109 | 31 | form = self.get_form() |
paul@19 | 32 | |
paul@128 | 33 | resolution = form.get("resolution", ["month"])[0] |
paul@128 | 34 | |
paul@19 | 35 | category_list = [] |
paul@112 | 36 | category_pagenames = form.get("category", []) |
paul@19 | 37 | |
paul@168 | 38 | for category_name, category_pagename in getCategoryMapping(getCategories(request), request): |
paul@19 | 39 | |
paul@112 | 40 | selected = self._get_selected_for_list(category_pagename, category_pagenames) |
paul@112 | 41 | |
paul@136 | 42 | category_list.append('<option value="%s" %s>%s</option>' % ( |
paul@136 | 43 | escattr(category_pagename), selected, escape(category_name))) |
paul@112 | 44 | |
paul@219 | 45 | sources_list = [] |
paul@219 | 46 | sources = form.get("source", []) |
paul@322 | 47 | source_names = (getAllEventSources(request) or {}).keys() |
paul@322 | 48 | source_names.sort() |
paul@219 | 49 | |
paul@322 | 50 | for source_name in source_names: |
paul@219 | 51 | |
paul@219 | 52 | selected = self._get_selected_for_list(source_name, sources) |
paul@219 | 53 | |
paul@219 | 54 | sources_list.append('<option value="%s" %s>%s</option>' % ( |
paul@219 | 55 | escattr(source_name), selected, escape(source_name))) |
paul@219 | 56 | |
paul@127 | 57 | # Initialise month lists and defaults. |
paul@19 | 58 | |
paul@112 | 59 | start_month_list, end_month_list = self.get_month_lists() |
paul@127 | 60 | start_day_default, end_day_default = self.get_day_defaults() |
paul@112 | 61 | start_year_default, end_year_default = self.get_year_defaults() |
paul@23 | 62 | |
paul@114 | 63 | # Criteria instead of months and years. |
paul@114 | 64 | |
paul@114 | 65 | start_criteria_default = form.get("start", [""])[0] |
paul@114 | 66 | end_criteria_default = form.get("end", [""])[0] |
paul@114 | 67 | |
paul@128 | 68 | if resolution == "date": |
paul@168 | 69 | get_parameter = getParameterDate |
paul@168 | 70 | get_label = getFullDateLabel |
paul@128 | 71 | else: |
paul@168 | 72 | get_parameter = getParameterMonth |
paul@168 | 73 | get_label = getFullMonthLabel |
paul@114 | 74 | |
paul@128 | 75 | start_criteria_evaluated = get_parameter(start_criteria_default) |
paul@128 | 76 | end_criteria_evaluated = get_parameter(end_criteria_default) |
paul@128 | 77 | |
paul@128 | 78 | start_criteria_evaluated = get_label(request, start_criteria_evaluated) |
paul@128 | 79 | end_criteria_evaluated = get_label(request, end_criteria_evaluated) |
paul@114 | 80 | |
paul@112 | 81 | # Descriptions. |
paul@112 | 82 | |
paul@112 | 83 | descriptions = form.get("descriptions", [None])[0] |
paul@23 | 84 | |
paul@45 | 85 | descriptions_list = [ |
paul@148 | 86 | '<option value="%s" %s>%s</option>' % ("page", self._get_selected("page", descriptions), escape(_("page"))), |
paul@148 | 87 | '<option value="%s" %s>%s</option>' % ("comment", self._get_selected("comment", descriptions), escape(_("comment"))) |
paul@45 | 88 | ] |
paul@45 | 89 | |
paul@112 | 90 | # Format. |
paul@112 | 91 | |
paul@112 | 92 | format = form.get("format", [None])[0] |
paul@112 | 93 | |
paul@45 | 94 | format_list = [ |
paul@148 | 95 | '<option value="%s" %s>%s</option>' % ("iCalendar", self._get_selected("iCalendar", format), escape(_("iCalendar"))), |
paul@148 | 96 | '<option value="%s" %s>%s</option>' % ("RSS", self._get_selected("RSS", format), escape(_("RSS 2.0"))) |
paul@45 | 97 | ] |
paul@23 | 98 | |
paul@115 | 99 | right_arrow = unicode('\xe2\x86\x92', "utf-8") |
paul@115 | 100 | |
paul@19 | 101 | d = { |
paul@74 | 102 | "buttons_html" : buttons_html, |
paul@137 | 103 | "category_label" : escape(_("Categories")), |
paul@74 | 104 | "category_list" : "\n".join(category_list), |
paul@219 | 105 | "sources_label" : escape(_("Sources")), |
paul@219 | 106 | "sources_list" : "\n".join(sources_list), |
paul@112 | 107 | "start_month_list" : "\n".join(start_month_list), |
paul@136 | 108 | "start_label" : escape(_("Start day (optional), month and year")), |
paul@136 | 109 | "start_day_default" : escattr(start_day_default), |
paul@148 | 110 | "start_year_default" : escattr(start_year_default), |
paul@148 | 111 | "start_criteria_label" : escape(_("or special criteria")), |
paul@148 | 112 | "start_criteria_default": escattr(start_criteria_default), |
paul@136 | 113 | "start_eval_label" : escattr(right_arrow), |
paul@148 | 114 | "start_criteria_eval" : escape(start_criteria_evaluated), |
paul@112 | 115 | "end_month_list" : "\n".join(end_month_list), |
paul@136 | 116 | "end_label" : escape(_("End day (optional), month and year")), |
paul@136 | 117 | "end_day_default" : escattr(end_day_default), |
paul@148 | 118 | "end_year_default" : escattr(end_year_default), |
paul@148 | 119 | "end_criteria_label" : escape(_("or special criteria")), |
paul@148 | 120 | "end_criteria_default" : escattr(end_criteria_default), |
paul@151 | 121 | "end_eval_label" : escattr(right_arrow), |
paul@148 | 122 | "end_criteria_eval" : escape(end_criteria_evaluated), |
paul@137 | 123 | "descriptions_label" : escape(_("Use descriptions from...")), |
paul@74 | 124 | "descriptions_list" : "\n".join(descriptions_list), |
paul@137 | 125 | "format_label" : escape(_("Summary format")), |
paul@74 | 126 | "format_list" : "\n".join(format_list), |
paul@137 | 127 | "parent_label" : escape(_("Parent page")), |
paul@137 | 128 | "parent_name" : escattr(form.get("parent", [""])[0]), |
paul@136 | 129 | "resolution" : escattr(resolution), |
paul@19 | 130 | } |
paul@10 | 131 | |
paul@19 | 132 | return ''' |
paul@131 | 133 | <input name="resolution" type="hidden" value="%(resolution)s" /> |
paul@19 | 134 | <table> |
paul@19 | 135 | <tr> |
paul@19 | 136 | <td class="label"><label>%(category_label)s</label></td> |
paul@19 | 137 | <td class="content"> |
paul@19 | 138 | <select multiple="multiple" name="category"> |
paul@19 | 139 | %(category_list)s |
paul@19 | 140 | </select> |
paul@19 | 141 | </td> |
paul@19 | 142 | </tr> |
paul@19 | 143 | <tr> |
paul@219 | 144 | <td class="label"><label>%(sources_label)s</label></td> |
paul@219 | 145 | <td class="content"> |
paul@219 | 146 | <select multiple="multiple" name="source"> |
paul@219 | 147 | %(sources_list)s |
paul@219 | 148 | </select> |
paul@219 | 149 | </td> |
paul@219 | 150 | </tr> |
paul@219 | 151 | <tr> |
paul@19 | 152 | <td class="label"><label>%(start_label)s</label></td> |
paul@22 | 153 | <td> |
paul@127 | 154 | <input name="start-day" type="text" value="%(start_day_default)s" size="2" /> |
paul@23 | 155 | <select name="start-month"> |
paul@112 | 156 | %(start_month_list)s |
paul@23 | 157 | </select> |
paul@23 | 158 | <input name="start-year" type="text" value="%(start_year_default)s" size="4" /> |
paul@19 | 159 | </td> |
paul@19 | 160 | </tr> |
paul@19 | 161 | <tr> |
paul@114 | 162 | <td class="label"><label>%(start_criteria_label)s</label></td> |
paul@114 | 163 | <td> |
paul@114 | 164 | <input name="start" type="text" value="%(start_criteria_default)s" size="12" /> |
paul@114 | 165 | <input name="start-eval" type="submit" value="%(start_eval_label)s" /> |
paul@114 | 166 | %(start_criteria_eval)s |
paul@114 | 167 | </td> |
paul@114 | 168 | </tr> |
paul@114 | 169 | <tr> |
paul@19 | 170 | <td class="label"><label>%(end_label)s</label></td> |
paul@22 | 171 | <td> |
paul@127 | 172 | <input name="end-day" type="text" value="%(end_day_default)s" size="2" /> |
paul@23 | 173 | <select name="end-month"> |
paul@112 | 174 | %(end_month_list)s |
paul@23 | 175 | </select> |
paul@23 | 176 | <input name="end-year" type="text" value="%(end_year_default)s" size="4" /> |
paul@19 | 177 | </td> |
paul@19 | 178 | </tr> |
paul@19 | 179 | <tr> |
paul@114 | 180 | <td class="label"><label>%(end_criteria_label)s</label></td> |
paul@114 | 181 | <td> |
paul@114 | 182 | <input name="end" type="text" value="%(end_criteria_default)s" size="12" /> |
paul@114 | 183 | <input name="end-eval" type="submit" value="%(end_eval_label)s" /> |
paul@114 | 184 | %(end_criteria_eval)s |
paul@114 | 185 | </td> |
paul@114 | 186 | </tr> |
paul@114 | 187 | <tr> |
paul@45 | 188 | <td class="label"><label>%(descriptions_label)s</label></td> |
paul@45 | 189 | <td class="content"> |
paul@45 | 190 | <select name="descriptions"> |
paul@45 | 191 | %(descriptions_list)s |
paul@45 | 192 | </select> |
paul@45 | 193 | </td> |
paul@45 | 194 | </tr> |
paul@45 | 195 | <tr> |
paul@45 | 196 | <td class="label"><label>%(format_label)s</label></td> |
paul@45 | 197 | <td class="content"> |
paul@45 | 198 | <select name="format"> |
paul@45 | 199 | %(format_list)s |
paul@45 | 200 | </select> |
paul@45 | 201 | </td> |
paul@45 | 202 | </tr> |
paul@45 | 203 | <tr> |
paul@74 | 204 | <td class="label"><label>%(parent_label)s</label></td> |
paul@74 | 205 | <td class="content"> |
paul@74 | 206 | <input name="parent" type="text" size="40" value="%(parent_name)s" /> |
paul@74 | 207 | </td> |
paul@74 | 208 | </tr> |
paul@74 | 209 | <tr> |
paul@19 | 210 | <td></td> |
paul@19 | 211 | <td class="buttons"> |
paul@19 | 212 | %(buttons_html)s |
paul@19 | 213 | </td> |
paul@19 | 214 | </tr> |
paul@19 | 215 | </table> |
paul@19 | 216 | ''' % d |
paul@19 | 217 | |
paul@19 | 218 | def do_action(self): |
paul@19 | 219 | |
paul@19 | 220 | "Write the iCalendar resource." |
paul@19 | 221 | |
paul@19 | 222 | _ = self._ |
paul@109 | 223 | form = self.get_form() |
paul@19 | 224 | |
paul@219 | 225 | # If no category names or sources exist in the request, an error message |
paul@219 | 226 | # is returned. |
paul@19 | 227 | |
paul@23 | 228 | category_names = form.get("category", []) |
paul@219 | 229 | sources = form.get("source", []) |
paul@19 | 230 | |
paul@219 | 231 | if not (category_names or sources): |
paul@219 | 232 | return 0, _("No categories or sources specified.") |
paul@19 | 233 | |
paul@19 | 234 | write_resource(self.request) |
paul@19 | 235 | return 1, None |
paul@19 | 236 | |
paul@27 | 237 | def render_success(self, msg, msgtype=None): |
paul@19 | 238 | |
paul@19 | 239 | """ |
paul@19 | 240 | Render neither 'msg' nor 'msgtype' since a resource has already been |
paul@19 | 241 | produced. |
paul@27 | 242 | NOTE: msgtype is optional because MoinMoin 1.5.x does not support it. |
paul@19 | 243 | """ |
paul@19 | 244 | |
paul@19 | 245 | pass |
paul@19 | 246 | |
paul@19 | 247 | def write_resource(request): |
paul@10 | 248 | |
paul@10 | 249 | """ |
paul@19 | 250 | For the given 'request', write an iCalendar summary of the event data found |
paul@19 | 251 | in the categories specified via the "category" request parameter, using the |
paul@19 | 252 | "start" and "end" parameters (if specified). Multiple "category" parameters |
paul@19 | 253 | can be specified. |
paul@10 | 254 | """ |
paul@10 | 255 | |
paul@168 | 256 | form = get_form(request) |
paul@46 | 257 | |
paul@46 | 258 | category_names = form.get("category", []) |
paul@219 | 259 | remote_sources = form.get("source", []) |
paul@46 | 260 | format = form.get("format", ["iCalendar"])[0] |
paul@46 | 261 | descriptions = form.get("descriptions", ["page"])[0] |
paul@74 | 262 | parent = form.get("parent", [""])[0] |
paul@142 | 263 | resolution = form.get("resolution", ["month"])[0] |
paul@10 | 264 | |
paul@143 | 265 | # Look first for a single start and end parameter. If that fails to provide |
paul@143 | 266 | # dates, look for separate start and end parameters, either for complete |
paul@143 | 267 | # dates or for years and months. |
paul@10 | 268 | |
paul@143 | 269 | if resolution == "date": |
paul@168 | 270 | calendar_start = getFormDate(request, None, "start") |
paul@168 | 271 | calendar_end = getFormDate(request, None, "end") |
paul@10 | 272 | |
paul@143 | 273 | if calendar_start is None: |
paul@168 | 274 | calendar_start = getFormDateTriple(request, "start-year", "start-month", "start-day") |
paul@143 | 275 | if calendar_end is None: |
paul@168 | 276 | calendar_end = getFormDateTriple(request, "end-year", "end-month", "end-day") |
paul@23 | 277 | |
paul@143 | 278 | elif resolution == "month": |
paul@168 | 279 | calendar_start = getFormMonth(request, None, "start") |
paul@168 | 280 | calendar_end = getFormMonth(request, None, "end") |
paul@23 | 281 | |
paul@143 | 282 | if calendar_start is None: |
paul@168 | 283 | calendar_start = getFormMonthPair(request, "start-year", "start-month") |
paul@143 | 284 | if calendar_end is None: |
paul@168 | 285 | calendar_end = getFormMonthPair(request, "end-year", "end-month") |
paul@127 | 286 | |
paul@127 | 287 | # Determine the period and get the events involved. |
paul@23 | 288 | |
paul@219 | 289 | pages = getPagesFromResults(getAllCategoryPages(category_names, request), request) |
paul@219 | 290 | events = getEventsFromResources(getEventPages(pages)) |
paul@219 | 291 | events += getEventsFromResources(getEventResources(remote_sources, calendar_start, calendar_end, request)) |
paul@219 | 292 | all_shown_events = getEventsInPeriod(events, getCalendarPeriod(calendar_start, calendar_end)) |
paul@310 | 293 | latest_timestamp = getLatestEventTimestamp(all_shown_events) |
paul@29 | 294 | |
paul@29 | 295 | # Output summary data... |
paul@10 | 296 | |
paul@238 | 297 | send_headers = get_send_headers(request) |
paul@27 | 298 | |
paul@29 | 299 | # Define headers. |
paul@29 | 300 | |
paul@29 | 301 | if format == "iCalendar": |
paul@29 | 302 | headers = ["Content-Type: text/calendar; charset=%s" % config.charset] |
paul@29 | 303 | elif format == "RSS": |
paul@29 | 304 | headers = ["Content-Type: application/rss+xml; charset=%s" % config.charset] |
paul@29 | 305 | |
paul@29 | 306 | # Define the last modified time. |
paul@10 | 307 | |
paul@38 | 308 | if latest_timestamp is not None: |
paul@219 | 309 | headers.append("Last-Modified: %s" % latest_timestamp.as_HTTP_datetime_string()) |
paul@38 | 310 | |
paul@29 | 311 | send_headers(headers) |
paul@29 | 312 | |
paul@29 | 313 | # iCalendar output... |
paul@10 | 314 | |
paul@29 | 315 | if format == "iCalendar": |
paul@307 | 316 | mimetype = "text/calendar" |
paul@29 | 317 | |
paul@127 | 318 | # RSS output... |
paul@127 | 319 | |
paul@29 | 320 | elif format == "RSS": |
paul@307 | 321 | mimetype = "application/rss+xml" |
paul@60 | 322 | |
paul@307 | 323 | # Catch-all... |
paul@45 | 324 | |
paul@307 | 325 | else: |
paul@307 | 326 | mimetype = None |
paul@10 | 327 | |
paul@307 | 328 | formatEventsForOutputType(all_shown_events, request, mimetype, parent, descriptions, latest_timestamp) |
paul@93 | 329 | |
paul@19 | 330 | # Action function. |
paul@19 | 331 | |
paul@19 | 332 | def execute(pagename, request): |
paul@19 | 333 | EventAggregatorSummary(pagename, request).render() |
paul@19 | 334 | |
paul@10 | 335 | # vim: tabstop=4 expandtab shiftwidth=4 |