1 # -*- coding: iso-8859-1 -*- 2 """ 3 MoinMoin - EventAggregatorNewEvent Action 4 5 @copyright: 2008, 2009, 2010, 2011, 2012 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.Page import Page 15 from MoinMoin.PageEditor import PageEditor 16 from MoinMoin import config 17 from EventAggregatorSupport import * 18 import re 19 20 try: 21 import pytz 22 except ImportError: 23 pytz = None 24 25 Dependencies = ['pages'] 26 27 # Action class and supporting functions. 28 29 class EventAggregatorNewEvent(ActionBase, ActionSupport): 30 31 "An event creation dialogue requesting various parameters." 32 33 def get_form_html(self, buttons_html): 34 _ = self._ 35 request = self.request 36 form = self.get_form() 37 38 # Handle advanced and basic forms, and enable/disable certain fields. 39 40 show_advanced = form.get("advanced") and not form.get("basic") 41 show_end_date = form.get("end-day") and not form.get("hide-end-date") or form.get("show-end-date") 42 show_times = (form.get("start-hour") or form.get("end-hour")) and not form.get("hide-times") or form.get("show-times") 43 show_location = form.get("show-location") or form.get("new-location") and not form.get("hide-location") 44 choose_page_name = form.get("page-name") and not form.get("auto-page-name") or form.get("choose-page-name") 45 46 # Define the overridden page name, if appropriate. 47 48 page_name = choose_page_name and form.get("page-name", ["@PARENT@/@TITLE@"])[0] or "" 49 50 # Prepare the category list. 51 52 category_list = [] 53 category_pagenames = form.get("category", []) 54 55 for category_name, category_pagename in getCategoryMapping(getCategories(request), request): 56 57 selected = self._get_selected_for_list(category_pagename, category_pagenames) 58 59 # In the advanced view, populate a menu. 60 61 if show_advanced: 62 category_list.append('<option value="%s" %s>%s</option>' % ( 63 escattr(category_pagename), selected, escape(category_name))) 64 65 # In the basic view, use hidden fields. 66 67 elif selected: 68 category_list.append('<input value="%s" name="category" type="hidden" />' % escattr(category_pagename)) 69 70 # Prepare the topics list. 71 72 topics = form.get("topics", []) 73 74 if form.get("add-topic"): 75 topics.append("") 76 else: 77 for i in range(0, len(topics)): 78 if form.get("remove-topic-%d" % i): 79 del topics[i] 80 break 81 82 # Initialise month lists. 83 84 start_month_list, end_month_list = self.get_month_lists(default_as_current=1) 85 start_year_default, end_year_default = self.get_year_defaults(default_as_current=1) 86 87 # Initialise the locations list. 88 89 locations_page = getLocationsPage(request) 90 locations = getWikiDict(locations_page, request) 91 92 locations_list = [] 93 locations_list.append('<option value=""></option>') 94 95 location = (form.get("location") or form.get("new-location") or [""])[0] 96 97 # Prepare the locations list, selecting the specified location. 98 99 if locations: 100 locations_list += self.get_option_list(location, locations) or [] 101 102 locations_list.sort() 103 104 # Initialise the time regime from the location. 105 106 start_regime = form.get("start-regime", [None])[0] 107 end_regime = form.get("end-regime", [None])[0] 108 109 if not start_regime: 110 start_regime = Location(location, locations).getTimeRegime() 111 end_regime = end_regime or start_regime 112 113 # Initialise regime lists. 114 115 start_regime_list = [] 116 start_regime_list.append('<option value="">%s</option>' % escape(_("<The event location (if known)>"))) 117 end_regime_list = [] 118 end_regime_list.append('<option value="">%s</option>' % escape(_("<Same as start time>"))) 119 120 # Prepare regime lists, selecting specified regimes. 121 122 if pytz is not None: 123 start_regime_list += self.get_option_list(start_regime, pytz.common_timezones) 124 end_regime_list += self.get_option_list(end_regime, pytz.common_timezones) 125 126 # Show time zone-related information depending on various fields. 127 128 show_zone_regime = ( 129 form.get("start-regime") # have a regime 130 and not form.get("show-offsets") # are not switching to offsets 131 and not form.get("hide-zone") # are not removing zone information 132 or form.get("show-regime") # are switching to a regime 133 or form.get("show-times") and start_regime # are showing times with a regime 134 ) 135 show_zone_offsets = ( 136 form.get("start-offset") # have an offset 137 and not form.get("show-regime") # are not switching to a regime 138 and not form.get("hide-zone") # are not removing zone information 139 or form.get("show-offsets") # are switching to offsets 140 ) 141 142 show_zones = show_zone_regime or show_zone_offsets 143 144 # Permitting configuration of the template name. 145 146 template_default = getattr(request.cfg, "event_aggregator_new_event_template", "EventTemplate") 147 148 d = { 149 "buttons_html" : buttons_html, 150 "form_trigger" : escattr(self.form_trigger), 151 "form_cancel" : escattr(self.form_cancel), 152 153 "category_label" : escape(_("Categories")), 154 "category_list" : "\n".join(category_list), 155 156 "start_month_list" : "\n".join(start_month_list), 157 "end_month_list" : "\n".join(end_month_list), 158 159 "start_regime_list" : "\n".join(start_regime_list), 160 "end_regime_list" : "\n".join(end_regime_list), 161 "use_regime_label" : escape(_("Using local time in...")), 162 163 "show_end_date_label" : escape(_("Specify end date")), 164 "hide_end_date_label" : escape(_("End event on same day")), 165 166 "show_times_label" : escape(_("Specify times")), 167 "hide_times_label" : escape(_("No start and end times")), 168 169 "show_offsets_label" : escape(_("Specify UTC offsets")), 170 "show_regime_label" : escape(_("Use local time")), 171 "hide_zone_label" : escape(_("Make times apply everywhere")), 172 173 "start_label" : escape(_("Start date (day, month, year)")), 174 "start_day_default" : escattr(form.get("start-day", [""])[0]), 175 "start_year_default" : escattr(start_year_default), 176 "start_time_label" : escape(_("Start time (hour, minute, second)")), 177 "start_hour_default" : escattr(form.get("start-hour", [""])[0]), 178 "start_minute_default" : escattr(form.get("start-minute", [""])[0]), 179 "start_second_default" : escattr(form.get("start-second", [""])[0]), 180 "start_offset_default" : escattr(form.get("start-offset", [""])[0]), 181 182 "end_label" : escape(_("End date (day, month, year) - if different")), 183 "end_day_default" : escattr(form.get("end-day", [""])[0].strip() or form.get("start-day", [""])[0]), 184 "end_year_default" : escattr(end_year_default), 185 "end_time_label" : escape(_("End time (hour, minute, second)")), 186 "end_hour_default" : escattr(form.get("end-hour", [""])[0]), 187 "end_minute_default" : escattr(form.get("end-minute", [""])[0]), 188 "end_second_default" : escattr(form.get("end-second", [""])[0]), 189 "end_offset_default" : escattr(form.get("end-offset", [""])[0].strip() or form.get("start-offset", [""])[0]), 190 191 "title_label" : escape(_("Event title/summary")), 192 "title_default" : escattr(form.get("title", [""])[0]), 193 "choose_page_name_label": escape(_("Choose page name")), 194 "auto_page_name_label" : escape(_("Auto page name")), 195 "page_name_label" : escape(_("Page name")), 196 "page_name_default" : escattr(form.get("page-name", [page_name])[0]), 197 "description_label" : escape(_("Event description")), 198 "description_default" : escattr(form.get("description", [""])[0]), 199 200 "location_label" : escape(_("Event location")), 201 "locations_list" : "\n".join(locations_list), 202 "show_location_label" : escattr(_("Specify a different location")), 203 "hide_location_label" : escattr(_("Choose a known location")), 204 "new_location" : escattr(form.get("new-location", [location])[0]), 205 206 "latitude_label" : escape(_("Latitude")), 207 "latitude_default" : escattr(form.get("latitude", [""])[0]), 208 "longitude_label" : escape(_("Longitude")), 209 "longitude_default" : escattr(form.get("longitude", [""])[0]), 210 "link_label" : escape(_("External URL")), 211 "link_default" : escattr(form.get("link", [""])[0]), 212 213 "topics_label" : escape(_("Topics")), 214 "add_topic_label" : escape(_("Add topic")), 215 "remove_topic_label" : escape(_("Remove topic")), 216 217 "template_label" : escape(_("Event template")), 218 "template_default" : escattr(form.get("template", [""])[0].strip() or template_default), 219 "parent_label" : escape(_("Parent page")), 220 "parent_default" : escattr(form.get("parent", [""])[0]), 221 222 "advanced_label" : escape(_("Show advanced options")), 223 "basic_label" : escape(_("Hide advanced options")), 224 } 225 226 # Prepare the output HTML. 227 228 html = ''' 229 <input name="update-form-only" value="false" type="hidden" /> 230 <table> 231 <tr> 232 <td class="label"><label>%(title_label)s</label></td> 233 <td colspan="2"> 234 <input name="title" type="text" size="40" value="%(title_default)s" /> 235 </td> 236 </tr>''' % d 237 238 # Page name options. 239 240 if choose_page_name: 241 html += ''' 242 <tr> 243 <td class="label"><label>%(page_name_label)s</label></td> 244 <td colspan="2"> 245 <input name="page-name" type="text" size="40" value="%(page_name_default)s" /> 246 </td> 247 <tr> 248 <td class="label"> 249 <input name="auto-page-name" type="submit" value="%(auto_page_name_label)s" /> 250 </td> 251 </tr>''' % d 252 else: 253 html += ''' 254 <tr> 255 <td class="label"> 256 <input name="choose-page-name" type="submit" value="%(choose_page_name_label)s" /> 257 </td> 258 </tr>''' % d 259 260 # Location options. 261 262 html += ''' 263 <tr> 264 <td class="label"><label>%(location_label)s</label></td> 265 <td colspan="2">''' % d 266 267 if not show_location: 268 html += ''' 269 <select name="location"> 270 %(locations_list)s 271 </select> 272 <input name="show-location" type="submit" value="%(show_location_label)s" />''' % d 273 274 else: 275 html += ''' 276 <input name="new-location" type="text" size="30" value="%(new_location)s" /> 277 <input name="hide-location" type="submit" value="%(hide_location_label)s" />''' % d 278 279 html += ''' 280 </td> 281 </tr>''' % d 282 283 # Latitude and longitude. 284 285 if show_location: 286 html += ''' 287 <tr> 288 <td class="label"><label>%(latitude_label)s</label></td> 289 <td colspan="2"> 290 <input name="latitude" type="text" size="40" value="%(latitude_default)s" /> 291 </td> 292 </tr> 293 <tr> 294 <td class="label"><label>%(longitude_label)s</label></td> 295 <td colspan="2"> 296 <input name="longitude" type="text" size="40" value="%(longitude_default)s" /> 297 </td> 298 </tr>''' % d 299 300 # Start date controls. 301 302 html += ''' 303 <tr> 304 <td class="label"><label>%(start_label)s</label></td> 305 <td colspan="2" style="white-space: nowrap"> 306 <input name="start-day" type="text" value="%(start_day_default)s" size="2" /> 307 <select name="start-month"> 308 %(start_month_list)s 309 </select> 310 <input name="start-year" type="text" value="%(start_year_default)s" size="4" /> 311 </td> 312 </tr>''' % d 313 314 # End date controls. 315 316 if show_end_date: 317 html += ''' 318 <tr> 319 <td class="label"><label>%(end_label)s</label></td> 320 <td colspan="2" style="white-space: nowrap"> 321 <input name="end-day" type="text" value="%(end_day_default)s" size="2" /> 322 <select name="end-month"> 323 %(end_month_list)s 324 </select> 325 <input name="end-year" type="text" value="%(end_year_default)s" size="4" /> 326 </td> 327 </tr> 328 <tr> 329 <td class="label"> 330 <input name="hide-end-date" type="submit" value="%(hide_end_date_label)s" /> 331 </td> 332 </tr>''' % d 333 else: 334 html += ''' 335 <tr> 336 <td class="label"> 337 <input name="show-end-date" type="submit" value="%(show_end_date_label)s" /> 338 </td> 339 </tr>''' % d 340 341 # Generic time information. 342 343 if show_times: 344 345 # Start time controls. 346 347 html += ''' 348 <tr> 349 <td class="label event-time-selection"><label>%(start_time_label)s</label></td> 350 <td style="white-space: nowrap" class="event-time-selection"> 351 <input name="start-hour" type="text" value="%(start_hour_default)s" size="2" maxlength="2" /> 352 <input name="start-minute" type="text" value="%(start_minute_default)s" size="2" maxlength="2" /> 353 <input name="start-second" type="text" value="%(start_second_default)s" size="2" maxlength="2" /> 354 </td>''' % d 355 356 # Offset information displayed. 357 358 if show_zone_offsets: 359 html += ''' 360 <td class="event-zone-selection"> 361 UTC <input name="start-offset" type="text" value="%(start_offset_default)s" size="6" maxlength="6" /> 362 </td>''' % d 363 364 # Regime information displayed. 365 366 elif show_zone_regime: 367 html += ''' 368 <td class="event-regime-selection"> 369 <label>%(use_regime_label)s</label><br/> 370 <select name="start-regime"> 371 %(start_regime_list)s 372 </select> 373 </td>''' % d 374 375 html += ''' 376 </tr>''' 377 378 # End time controls. 379 380 html += ''' 381 <tr> 382 <td class="label event-time-selection"><label>%(end_time_label)s</label></td> 383 <td style="white-space: nowrap" class="event-time-selection"> 384 <input name="end-hour" type="text" value="%(end_hour_default)s" size="2" maxlength="2" /> 385 <input name="end-minute" type="text" value="%(end_minute_default)s" size="2" maxlength="2" /> 386 <input name="end-second" type="text" value="%(end_second_default)s" size="2" maxlength="2" /> 387 </td>''' % d 388 389 # Offset information displayed. 390 391 if show_zone_offsets: 392 html += ''' 393 <td class="event-zone-selection"> 394 UTC <input name="end-offset" type="text" value="%(end_offset_default)s" size="6" maxlength="6" /> 395 </td>''' % d 396 397 # Regime information displayed. 398 399 elif show_zone_regime: 400 html += ''' 401 <td class="event-regime-selection event-end-time"> 402 <select name="end-regime"> 403 %(end_regime_list)s 404 </select> 405 </td>''' % d 406 407 # Controls for removing times. 408 409 html += ''' 410 </tr> 411 <tr> 412 <td class="label"> 413 <input name="hide-times" type="submit" value="%(hide_times_label)s" /> 414 </td> 415 <td></td> 416 <td>''' % d 417 418 # Time zone controls. 419 420 if show_zones: 421 422 # To remove zone information. 423 424 html += ''' 425 <input name="hide-zone" type="submit" value="%(hide_zone_label)s" />''' % d 426 427 # No time zone information shown. 428 429 else: 430 html += ''' 431 <input name="show-regime" type="submit" value="%(show_regime_label)s" /> 432 <input name="show-offsets" type="submit" value="%(show_offsets_label)s" />''' % d 433 434 html += ''' 435 </td> 436 </tr>''' 437 438 # Controls for adding times. 439 440 else: 441 html += ''' 442 <tr> 443 <td class="label"> 444 <input name="show-times" type="submit" value="%(show_times_label)s" /> 445 </td> 446 </tr>''' % d 447 448 449 # Various basic controls. 450 451 html += ''' 452 <tr> 453 <td class="label"><label>%(description_label)s</label></td> 454 <td colspan="2"> 455 <input name="description" type="text" size="40" value="%(description_default)s" /> 456 </td> 457 </tr> 458 <tr> 459 <td class="label"><label>%(link_label)s</label></td> 460 <td colspan="2"> 461 <input name="link" type="text" size="40" value="%(link_default)s" /> 462 </td> 463 </tr>''' % d 464 465 # Topics. 466 467 for i, topic in enumerate(topics): 468 d["topic"] = escattr(topic) 469 d["topic_number"] = i 470 html += ''' 471 <tr> 472 <td class="label"><label>%(topics_label)s</label></td> 473 <td colspan="2"> 474 <input name="topics" type="text" size="20" value="%(topic)s" /> 475 <input name="remove-topic-%(topic_number)s" type="submit" value="%(remove_topic_label)s" /> 476 </td> 477 </tr>''' % d 478 479 html += ''' 480 <tr> 481 <td></td> 482 <td colspan="2"> 483 <input name="add-topic" type="submit" value="%(add_topic_label)s" /> 484 </td> 485 </tr>''' % d 486 487 # Advanced options. 488 489 if show_advanced: 490 html += ''' 491 <tr> 492 <td></td> 493 <td colspan="2"> 494 <input name="basic" type="submit" value="%(basic_label)s" /> 495 <input name="advanced" type="hidden" value="true" /> 496 </td> 497 </tr> 498 <tr> 499 <td class="label"><label>%(category_label)s</label></td> 500 <td colspan="2" class="content"> 501 <select multiple="multiple" name="category"> 502 %(category_list)s 503 </select> 504 </td> 505 </tr> 506 <tr> 507 <td class="label"><label>%(template_label)s</label></td> 508 <td colspan="2"> 509 <input name="template" type="text" size="40" value="%(template_default)s" /> 510 </td> 511 </tr> 512 <tr> 513 <td class="label"><label>%(parent_label)s</label></td> 514 <td colspan="2"> 515 <input name="parent" type="text" size="40" value="%(parent_default)s" /> 516 </td> 517 </tr> 518 <tr> 519 <td></td> 520 <td colspan="2" class="buttons"> 521 %(buttons_html)s 522 </td> 523 </tr> 524 </table>''' % d 525 else: 526 html += ''' 527 <tr> 528 <td></td> 529 <td colspan="2"> 530 <input name="advanced" type="submit" value="%(advanced_label)s" /> 531 %(category_list)s 532 <input name="parent" type="hidden" value="%(parent_default)s" /> 533 <input name="template" type="hidden" value="%(template_default)s" /> 534 </td> 535 </tr> 536 <tr> 537 <td></td> 538 <td colspan="2" class="buttons"> 539 %(buttons_html)s 540 </td> 541 </tr> 542 </table> 543 <script type="text/javascript"> 544 function replaceDialog(url, button) { 545 var form = findForm(); 546 var dialog = findDialog(document); 547 if (form != null && dialog != null) { 548 var xmlhttp = new XMLHttpRequest(); 549 xmlhttp.open("POST", url, false); 550 xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 551 552 var requestBody = encodeURIComponent(button.name) + "=" + encodeURIComponent(button.value); 553 for (var i = 0; i < form.elements.length; i++) { 554 var element = form.elements[i]; 555 if (element.type != "submit") { 556 requestBody += "&" + encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value); 557 } 558 } 559 xmlhttp.send(requestBody); 560 561 var newDialog = xmlhttp.responseText; 562 563 if (newDialog != null) { 564 dialog.parentNode.innerHTML = newDialog; 565 initForm(); 566 return false; 567 } 568 } 569 } 570 571 function findDialog(d) { 572 var elements = d.getElementsByTagName("div"); 573 for (var i = 0; i < elements.length; i++) { 574 var element = elements[i]; 575 var cls = element.getAttribute("class"); 576 if (cls == "dialog") { 577 return element; 578 } 579 } 580 return null; 581 } 582 583 function findForm() { 584 for (var i = 0; i < document.forms.length; i++) { 585 var form = document.forms[i]; 586 if (form["update-form-only"] != null) { 587 return form; 588 } 589 } 590 return null; 591 } 592 593 function initForm() { 594 var form = findForm(); 595 var url = form.getAttribute("action"); 596 form["update-form-only"].value = "true"; 597 for (var i = 0; i < form.length; i++) { 598 var element = form[i]; 599 if (element.type == "submit" && element.name != "%(form_trigger)s" && element.name != "%(form_cancel)s") { 600 element.setAttribute("onclick", "return replaceDialog('" + url + "', this);"); 601 } 602 } 603 } 604 605 initForm(); 606 </script>''' % d 607 608 return html 609 610 def do_action(self): 611 612 "Create the new event." 613 614 _ = self._ 615 form = self.get_form() 616 617 # If no title exists in the request, an error message is returned. 618 619 title = form.get("title", [None])[0] 620 template = form.get("template", [None])[0] 621 622 if not title: 623 return 0, _("No event title specified.") 624 625 if not template: 626 return 0, _("No page template specified.") 627 628 return self.create_event(self.request) 629 630 def render_msg(self, msg, msgtype): 631 632 """ 633 Render 'msg' and 'msgtype'. If 'msgtype' is "dialog" then the form is 634 rendered, and if only part of the form is being requested, the output 635 will be only the form HTML fragment and not the entire page. 636 """ 637 638 # Either render the form as a fragment of a page. 639 640 form = self.get_form() 641 update_form_only = form.get("update-form-only", ["false"])[0] == "true" 642 action_attempted = form.has_key(self.form_trigger) 643 644 if msgtype == "dialog" and update_form_only and not action_attempted: 645 send_headers = get_send_headers(self.request) 646 send_headers(["Content-Type: text/html; charset=%s" % config.charset]) 647 self.request.write(msg.render()) 648 649 # Or render the message/form within an entire page. 650 651 else: 652 ActionBase.render_msg(self, msg, msgtype) 653 654 def render_success(self, msg, msgtype): 655 656 """ 657 Render neither 'msg' nor 'msgtype' since redirection should occur 658 instead. 659 """ 660 661 pass 662 663 def create_event(self, request): 664 665 "Create an event page using the 'request'." 666 667 _ = request.getText 668 form = self.get_form() 669 670 category_pagenames = form.get("category", []) 671 description = form.get("description", [None])[0] 672 location = (form.get("location") or form.get("new-location") or [""])[0] 673 latitude = form.get("latitude", [None])[0] 674 longitude = form.get("longitude", [None])[0] 675 link = form.get("link", [None])[0] 676 topics = form.get("topics", []) 677 678 start_regime = form.get("start-regime", [None])[0] 679 end_regime = form.get("end-regime", form.get("start-regime", [None]))[0] 680 start_offset = form.get("start-offset", [None])[0] 681 end_offset = form.get("end-offset", [None])[0] 682 683 start_zone = start_regime or start_offset 684 end_zone = end_regime or end_offset 685 686 page_name = form.get("page-name", [None])[0] 687 688 # Validate certain fields. 689 690 title = form.get("title", [""])[0].strip() 691 template = form.get("template", [""])[0].strip() 692 parent = form.get("parent", [""])[0].strip() 693 694 if not title: 695 return 0, _("No event title specified.") 696 if not template: 697 return 0, _("No event template specified.") 698 699 try: 700 start_day = self._get_input(form, "start-day") 701 start_month = self._get_input(form, "start-month") 702 start_year = self._get_input(form, "start-year") 703 704 if not start_day or not start_month or not start_year: 705 return 0, _("A start date must be specified.") 706 707 end_day = self._get_input(form, "end-day", start_day) 708 end_month = self._get_input(form, "end-month", start_month) 709 end_year = self._get_input(form, "end-year", start_year) 710 711 except (TypeError, ValueError): 712 return 0, _("Days and years must be numbers yielding a valid date!") 713 714 try: 715 start_hour = self._get_input(form, "start-hour") 716 start_minute = self._get_input(form, "start-minute") 717 start_second = self._get_input(form, "start-second") 718 719 end_hour = self._get_input(form, "end-hour") 720 end_minute = self._get_input(form, "end-minute") 721 end_second = self._get_input(form, "end-second") 722 723 except (TypeError, ValueError): 724 return 0, _("Hours, minutes and seconds must be numbers yielding a valid time!") 725 726 start_date = DateTime( 727 (start_year, start_month, start_day, start_hour, start_minute, start_second, start_zone) 728 ) 729 start_date.constrain() 730 731 end_date = DateTime( 732 (end_year, end_month, end_day, end_hour, end_minute, end_second, end_zone) 733 ) 734 end_date.constrain() 735 736 # An elementary date ordering check. 737 738 if (start_date.as_date() != end_date.as_date() or start_date.has_time() and end_date.has_time()) and start_date > end_date: 739 start_date, end_date = end_date, start_date 740 741 event_details = { 742 "start" : str(start_date), "end" : str(end_date), 743 "title" : title, "summary" : title, 744 "description" : description, "location" : location, "link" : link, 745 "topics" : [topic for topic in topics if topic] 746 } 747 748 if latitude and longitude: 749 event_details["geo"] = latitude, longitude 750 751 # Copy the template. 752 753 template_page = PageEditor(request, template) 754 755 if not template_page.exists(): 756 return 0, _("Event template not available.") 757 758 # Use any parent page information. 759 760 full_title = getFullPageName(parent, title) 761 762 if page_name: 763 764 # Allow parameters in the page name. This permits a degree of 765 # interoperability with MonthCalendar. 766 767 page_name = page_name.replace("@PAGE@", request.page.page_name) 768 page_name = page_name.replace("@DATE@", str(start_date.as_date())) 769 page_name = page_name.replace("@STARTDATE@", str(start_date.as_date())) 770 page_name = page_name.replace("@ENDDATE@", str(end_date.as_date())) 771 page_name = page_name.replace("@PARENT@", parent) 772 page_name = page_name.replace("@TITLE@", title) 773 774 # Normalise any page hierarchy separators. 775 776 page_name = re.sub("/+", "/", page_name) 777 778 else: 779 page_name = full_title 780 781 # Load the new page and replace the event details in the body. 782 783 new_page = PageEditor(request, page_name) 784 785 if new_page.exists(): 786 return 0, _("The specified page already exists. Please choose another name.") 787 788 # Complete the new page and return its body. 789 790 body = fillEventPageFromTemplate(template_page, new_page, event_details, category_pagenames) 791 792 # Open the page editor on the new page. 793 # NOTE: Replacing the revision in the request to prevent Moin from 794 # NOTE: attempting to use the queued changes page's revision. 795 # NOTE: Replacing the action and page in the request to avoid issues 796 # NOTE: with editing tickets. 797 798 request.rev = 0 799 request.action = "edit" 800 request.page = new_page 801 new_page.sendEditor(preview=body, staytop=True) 802 803 # Return success. 804 805 return 1, None 806 807 # Action function. 808 809 def execute(pagename, request): 810 EventAggregatorNewEvent(pagename, request).render() 811 812 # vim: tabstop=4 expandtab shiftwidth=4