Parent Directory
|
Revision Log
|
Revision Graph
My patch version2 of event.module for Drupal 4.5
| 1 | <?php |
| 2 | // $Id: event.module, frjo Exp $ |
| 3 | |
| 4 | /** |
| 5 | * Retrieves all of the fields from fields.inc. To add extra fields you might need, add them to the file called |
| 6 | * fields.inc in the event module directory. |
| 7 | * |
| 8 | * This version add end time, you need to add a end field to the event table: |
| 9 | * ALTER TABLE event ADD end int(10) unsigned NOT NULL default '0'; |
| 10 | * |
| 11 | * You probably need to change the time zone for the iCalender. |
| 12 | * Do a search/replace for "Europe/Stockholm" to whatever you want. |
| 13 | * I know, this you be set automatically or via a setting. |
| 14 | * |
| 15 | * This version of the event.module can be downloaded from my sandbox |
| 16 | * <http://cvs.drupal.org/viewcvs/drupal/contributions/sandbox/frjo/> |
| 17 | * |
| 18 | * @return an array of fields |
| 19 | */ |
| 20 | function event_fields() { |
| 21 | if (file_exists('modules/event/fields.inc')) { |
| 22 | include_once 'modules/event/fields.inc'; |
| 23 | return event_extra_fields(); |
| 24 | } |
| 25 | |
| 26 | return array(); |
| 27 | } |
| 28 | |
| 29 | /** |
| 30 | * Displays the help text for this module. |
| 31 | * |
| 32 | * @param $section the page which is requesting help |
| 33 | * @return the help text |
| 34 | */ |
| 35 | function event_help($section) { |
| 36 | switch ($section) { |
| 37 | case 'admin/modules#description': |
| 38 | return t('Lets users make events and keep calendars.'); |
| 39 | case 'node/add/event': |
| 40 | return variable_get('event_help', ''); |
| 41 | case 'node/add#event': |
| 42 | return t('Events are happenings scheduled for a specific date and time.'); |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | /** |
| 47 | * Provides a link to the CSS stylesheet associated with this module. |
| 48 | * |
| 49 | * @return a <style> tag that indicates what file browsers should import |
| 50 | */ |
| 51 | function event_html_head() { |
| 52 | return '<style type="text/css">@import url(modules/event/event.css);</style>'; |
| 53 | } |
| 54 | |
| 55 | /** |
| 56 | * Provides the blocks that this module is capable of displaying. |
| 57 | * |
| 58 | * @param $op the operation that is being requested. This defaults to 'list', which indicates that the method should |
| 59 | * which blocks are available. |
| 60 | * @param $delta the specific block to display. This is actually the offset into an array. |
| 61 | * @return one of two possibilities. The first is an array of available blocks. The other is an array containing a |
| 62 | * block. |
| 63 | */ |
| 64 | function event_block($op = 'list', $delta = 0) { |
| 65 | if ($op == 'list') { |
| 66 | $blocks[0]['info'] = t('Calendar to browse events.'); |
| 67 | $blocks[1]['info'] = t('List of upcoming events.'); |
| 68 | return $blocks; |
| 69 | } |
| 70 | else { |
| 71 | if (($op == 'view') && user_access('access content')) { |
| 72 | switch ($delta) { |
| 73 | case 0: |
| 74 | $block['subject'] = t('Browse events'); |
| 75 | $block['content'] = event_display('event_calendar_simple', $year, $month, $day); |
| 76 | return $block; |
| 77 | case 1: |
| 78 | $ical_url = l(t('subscribe iCal'), 'event/ical', array('title' => t('Add this calendar to your iCalendar')), NULL, NULL, true); |
| 79 | $ical_url = preg_replace("|http://|","webcal://", $ical_url); |
| 80 | |
| 81 | $block['subject'] = t('Upcoming events'); |
| 82 | $block['content'] = event_block_upcoming(); |
| 83 | $block['content'] .= '<div class="more-link">'. $ical_url .' | '. l(t('more'), 'event', array('title' => t('More events.'))) .'</div>'; |
| 84 | return $block; |
| 85 | } |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * Displays and allows an administrator to change the settings for this module. |
| 92 | * |
| 93 | * @return the content for a settings page. |
| 94 | */ |
| 95 | function event_settings() { |
| 96 | $output = form_textarea(t('Explanation or submission guidelines'), 'event_help', variable_get('event_help', ''), 70, 5, t('This text will be displayed at the top of the event submission form. Useful for helping or instructing your users.')); |
| 97 | $output .= form_radios(t('Time notation preference'), 'event_ampm', variable_get('event_ampm', '0'), array('0' => t('24h'), '1' => t('12h')), t('The time notation system used for entering event start times.')); |
| 98 | $output .= form_radios(t('Timezone handling'), 'event_timezone', variable_get('event_timezone', '1'), array('1' => t('Yes'), '0' => t('No')), t("Yes: Times are saved relative to the user's timezone. No: Times are displayed exactly as the user inputted them.")); |
| 99 | $output .= form_select(t('Type of overview'), 'event_overview', variable_get('event_overview', 'calendar'), array('calendar' => t('Calendar'), 'table' => t('Table')), t('The type of overview to show the user when he clicks on the block calendar.')); |
| 100 | |
| 101 | $extra = event_fields(); |
| 102 | $headerarray = array(); |
| 103 | foreach($extra as $key => $value) { |
| 104 | if ($value[0] == ('textfield' || 'textarea' || 'select') && $value[3]) { |
| 105 | $headerarray['e.'. $key] = $value[1]; |
| 106 | } |
| 107 | } |
| 108 | $headerarray = array_merge(array('e.start' => t('Date'), 'n.title' => t('Title'), 'n.teaser' => t('Teaser'), 'n.body' => t('Body')), $headerarray); |
| 109 | $output .= form_select(t('Table headers'), 'event_table_headers', variable_get('event_table_headers', array('e.start', 'n.title', 'n.teaser')), $headerarray, t('The table headers used in the table view. Only entries that have their own database column in the event table and are of type "textfield", "textarea", or "select" can be used.'), 0, 1); |
| 110 | |
| 111 | // Dummy arrays to be used by extractor.php |
| 112 | // Dummy array with abbreviations of months. |
| 113 | $month_abbr_dummy = array(t('Jan'), t('Feb'), t('Mar'), t('Apr'), t('May'), t('Jun'), t('Jul'), t('Aug'), t('Sep'), t('Oct'), t('Nov'), t('Dec')); |
| 114 | return $output; |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | * Displays a page containing event information. The page layout defaults to a graphical calendar. |
| 119 | */ |
| 120 | function event_page() { |
| 121 | $breadcrumbs = array( |
| 122 | l(t('Home'), NULL), |
| 123 | l(t('Events'), 'event') |
| 124 | ); |
| 125 | |
| 126 | if (arg(1) == 'search') { |
| 127 | $breadcrumbs[] = l(t('Search'), 'event/search'); |
| 128 | print theme('page', event_query(), t('Search Events'), $breadcrumbs); |
| 129 | return; |
| 130 | } |
| 131 | elseif (!arg(1)) { |
| 132 | global $user; |
| 133 | $time = time(); |
| 134 | $result = pager_query('SELECT DISTINCT(n.nid), e.start FROM {event} e INNER JOIN {node} n USING (nid) '. node_access_join_sql() .' WHERE '. node_access_where_sql() ." AND n.status = 1 AND e.start >= $time ORDER BY e.start", variable_get('default_nodes_main', 10)); |
| 135 | if (db_num_rows($result)) { |
| 136 | $output = ""; |
| 137 | $breadcrumbs[] = t('Upcoming'); |
| 138 | while ($node = db_fetch_object($result)) { |
| 139 | unset($node->start); // we need to select e.start for pgsql's sake but it confuses node_load. |
| 140 | $output .= node_view(node_load($node), 1); |
| 141 | } |
| 142 | $output .= theme("pager", NULL, variable_get('default_nodes_main', 10)); |
| 143 | print theme('page', $output, t('Upcoming events'), $breadcrumbs); |
| 144 | return; |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | // Show calendar by default |
| 149 | if (arg(1) == 'today') { |
| 150 | $current = event_format_date(time(), 'custom', 'Y/m/d'); |
| 151 | $pieces = explode('/', $current); |
| 152 | $year = $pieces[0]; |
| 153 | $month = $pieces[1]; |
| 154 | $day = $pieces[2]; |
| 155 | } |
| 156 | else { |
| 157 | $year = arg(1); $month = arg(2); $day = arg(3); |
| 158 | } |
| 159 | |
| 160 | $output = '<div id="event">'; |
| 161 | if (variable_get('event_overview', 'calendar') == 'table') { |
| 162 | $output .= event_display('event_table', $year, $month, $day, 1, 1); |
| 163 | } |
| 164 | else { |
| 165 | $output .= event_display('event_calendar_expanded', $year, $month, $day, 1); |
| 166 | } |
| 167 | $ical_url = l(t('subscribe iCal'), 'event/ical', array('title' => t('Add this calendar to your iCalendar')), NULL, NULL, true); |
| 168 | $ical_url = preg_replace("|http://|","webcal://", $ical_url); |
| 169 | $output .= '<br />'.theme('links', array(l(t('search events'), "event/search"), $ical_url)); |
| 170 | $output .= '</div>'; |
| 171 | |
| 172 | $timestamp = gmmktime(0, 0, 0, $month, ($day ? $day : 1), $year); |
| 173 | $breadcrumbs[] = l($year, "event/$year"); |
| 174 | $breadcrumbs[] = l(t(format_date($timestamp, 'custom', 'F', 0)), "event/$year/$month"); |
| 175 | print theme('page', $output, t('Events'), $breadcrumbs); |
| 176 | } |
| 177 | |
| 178 | /** |
| 179 | * Provides an array of permissions associated with this module. |
| 180 | * |
| 181 | * @return an array of permissions |
| 182 | */ |
| 183 | function event_perm() { |
| 184 | return array('maintain events'); |
| 185 | } |
| 186 | |
| 187 | /** |
| 188 | * Provides the links that should be displayed when viewing events. |
| 189 | * |
| 190 | * @param $type the type of link (for example, 'node', 'page', or 'system') being requested |
| 191 | * @param $node the node that is requesting the link. This is used in conjunction with $type to further determine |
| 192 | * what sort of link to display. |
| 193 | * @param $main unused in this method. |
| 194 | * @return an array of links, or an empty array if no links apply for the criteria passed to this method. |
| 195 | */ |
| 196 | function event_link($type, $node = 0, $main) { |
| 197 | |
| 198 | switch ($type) { |
| 199 | case 'node': |
| 200 | if ($node->type == 'event') { |
| 201 | if (node_access('update', $node) && !user_access('administer nodes')) { |
| 202 | $links[] = l(t('edit event'), "node/$node->nid/edit", array('title' => t('Edit this event.'))); |
| 203 | } |
| 204 | else { |
| 205 | $links[] = l(t('calendar'), 'event/'. event_format_date($node->start, 'custom', 'Y/m/d')); |
| 206 | } |
| 207 | } |
| 208 | break; |
| 209 | case 'page': |
| 210 | if (user_access('access content')) { |
| 211 | $links[] = l(t('events'), 'event', array('title' => t('Show events'))); |
| 212 | } |
| 213 | break; |
| 214 | } |
| 215 | |
| 216 | return $links ? $links : array(); |
| 217 | } |
| 218 | |
| 219 | /** |
| 220 | * Implementation of hook_cron(). |
| 221 | * It finds the last and the first event to limit links created by the calendars. |
| 222 | */ |
| 223 | function event_cron() { |
| 224 | if (time() - variable_set('event_cron_run', 0) > 600) { |
| 225 | $max = db_fetch_object(db_query('SELECT MAX(start) AS max FROM {event}')); |
| 226 | $min = db_fetch_object(db_query('SELECT MIN(start) AS min FROM {event}')); |
| 227 | variable_set('event_start_max', $max->max); |
| 228 | variable_set('event_start_min', $min->min); |
| 229 | variable_set('event_cron_run', time()); |
| 230 | } |
| 231 | } |
| 232 | |
| 233 | /** |
| 234 | * Implementation of hook_menu() |
| 235 | */ |
| 236 | function event_menu($may_cache) { |
| 237 | global $user; |
| 238 | |
| 239 | $items = array(); |
| 240 | if ($may_cache) { |
| 241 | $items[] = array('path' => 'node/add/event', 'title' => t('event'), |
| 242 | 'access' => user_access('maintain events')); |
| 243 | $items[] = array('path' => 'event', 'title' => t('events'), |
| 244 | 'callback' => 'event_page', |
| 245 | 'access' => user_access('access content'), |
| 246 | 'type' => MENU_SUGGESTED_ITEM); |
| 247 | $items[] = array('path' => 'event/'.event_format_date(time(), 'custom', 'Y/m/d'), 'title' => t('calendar'), |
| 248 | 'access' => user_access('access content'), |
| 249 | 'type' => MENU_DYNAMIC_ITEM); |
| 250 | $items[] = array('path' => 'event/search', 'title' => t('search'), |
| 251 | 'callback' => 'event_page', |
| 252 | 'type' => MENU_SUGGESTED_ITEM); |
| 253 | $items[] = array('path' => 'event/ical', 'title' => t('iCal'), |
| 254 | 'access' => user_access('access content'), |
| 255 | 'callback' => '_event_ical', |
| 256 | 'type' => MENU_SUGGESTED_ITEM); |
| 257 | } |
| 258 | else { |
| 259 | drupal_set_html_head(event_html_head()); |
| 260 | } |
| 261 | |
| 262 | return $items; |
| 263 | } |
| 264 | |
| 265 | /** |
| 266 | * @defgroup event_node Methods that implement node hooks. |
| 267 | */ |
| 268 | |
| 269 | /** |
| 270 | * Indicates what type of nodes this module generates. |
| 271 | * |
| 272 | * @ingroup event_node |
| 273 | * @return the type of node |
| 274 | */ |
| 275 | function event_node_name() { |
| 276 | return t('event'); |
| 277 | } |
| 278 | |
| 279 | /** |
| 280 | * Determines whether a user has permission to execute a specified operation. When no permission |
| 281 | * is specified, the node_access table determines access |
| 282 | * |
| 283 | * @ingroup event_node |
| 284 | * @param $op the operation that is being requested. |
| 285 | * @param &$node the node on which the operation will be executed. |
| 286 | * @return whether the user has sufficient access to execute the operation. |
| 287 | */ |
| 288 | function event_access($op, &$node) { |
| 289 | global $user; |
| 290 | switch ($op) { |
| 291 | case 'create': |
| 292 | return user_access('maintain events'); |
| 293 | case 'update': |
| 294 | if ($user->uid == $node->uid && user_access('maintain events')) { |
| 295 | return TRUE; |
| 296 | } |
| 297 | case 'delete': |
| 298 | if ($user->uid == $node->uid && user_access('maintain events')) { |
| 299 | return TRUE; |
| 300 | } |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | /** |
| 305 | * Verifies that the details of an event are properly set. |
| 306 | * - Changes 24 hour time to 12 hour time (if the module is configured to do this). |
| 307 | * - Adjusts times for timezone offsets. |
| 308 | * - Verifies that all required fields have values. |
| 309 | * |
| 310 | * @ingroup event_node |
| 311 | * @param &$node the event node to validate |
| 312 | * @return any error messages this method generates. |
| 313 | */ |
| 314 | function event_validate(&$node) { |
| 315 | // Re-calculate $node->start and $node->end if we have all the parameters. |
| 316 | event_validate_time($node, 'start'); |
| 317 | event_validate_time($node, 'end'); |
| 318 | |
| 319 | $fields = event_fields(); |
| 320 | foreach ($fields as $field => $def) { |
| 321 | if ($def[2] && isset($node->$field) && empty($node->$field)) { |
| 322 | form_set_error($field, t($def[1]).' '.t('is a required field.')); |
| 323 | } |
| 324 | } |
| 325 | if (isset($node->body) && empty($node->body)) { |
| 326 | form_set_error('body', t('Specify details for this event')); |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | |
| 331 | function event_validate_time(&$node, $time) { |
| 332 | $year = $time . '_year'; |
| 333 | $month = $time . '_month'; |
| 334 | $day = $time . '_day'; |
| 335 | $hour = $time . '_hour'; |
| 336 | $minute = $time . '_minute'; |
| 337 | $ampm = $time . '_ampm'; |
| 338 | if (isset($node->$year) && isset($node->$month) && isset($node->$day) && isset($node->$hour) && isset($node->$minute)) { |
| 339 | $the_hour = $node->$hour; |
| 340 | if (variable_get('event_ampm', '0')) { |
| 341 | if ($node->$ampm == 'pm' && $the_hour != 12) { |
| 342 | $the_hour += 12; |
| 343 | } |
| 344 | if ($the_hour == 12 && $node->$ampm == 'am') { |
| 345 | $the_hour -= 12; |
| 346 | } |
| 347 | } |
| 348 | $node->$time = _event_mktime($the_hour, $node->$minute, 0, $node->$month, $node->$day, $node->$year); |
| 349 | if (variable_get('event_timezone', '1')) { |
| 350 | $node->$time -= $GLOBALS['user']->timezone; |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | if (empty($node->$time)) { |
| 355 | if ($time == 'start') { |
| 356 | $node->$time = time(); |
| 357 | } |
| 358 | else { |
| 359 | $node->$time = $node->start - 0; |
| 360 | } |
| 361 | // Round to nearest hour: |
| 362 | $node->$time -= $node->$time % (60 * 60); |
| 363 | } |
| 364 | } |
| 365 | |
| 366 | |
| 367 | /** |
| 368 | * Completes an event node by setting the teaser and body fields. |
| 369 | * |
| 370 | * @ingroup event_node |
| 371 | * @param &$node the node to be completed |
| 372 | * @param $main unused in this method |
| 373 | * @return the same node passed with the teaser and body fields properly set |
| 374 | */ |
| 375 | function event_content(&$node, $main = 0) { |
| 376 | $fields = event_fields(); |
| 377 | |
| 378 | $output = '<div class="event">'; |
| 379 | $output .= '<div class="details">'; |
| 380 | $output .= form_item(t('Start'), event_format_date($node->start, 'large')); |
| 381 | if ($node->end > $node->start) { |
| 382 | $output .= form_item(t('End'), event_format_date($node->end, 'large')); |
| 383 | } |
| 384 | foreach ($fields as $field => $def) { |
| 385 | if ($node->$field) { |
| 386 | if ($def[0] == "select") { |
| 387 | if ($def[10]) { // multi-select |
| 388 | foreach ($node->$field as $val) { |
| 389 | $vals[] = $def[7][$val]; |
| 390 | } |
| 391 | $output .= form_item($def[1], implode(", ", $vals)); |
| 392 | } |
| 393 | else { |
| 394 | $output .= form_item($def[1], $def[7][$node->$field]); |
| 395 | } |
| 396 | } |
| 397 | else { |
| 398 | $output .= form_item($def[1], $node->$field); |
| 399 | } |
| 400 | } |
| 401 | } |
| 402 | $output .= '</div>'; |
| 403 | |
| 404 | $node->teaser = $output . ($node->teaser ? '<div class="content">'. check_output($node->teaser, $node->format) .'</div></div>' : '</div>'); |
| 405 | $node->body = $output . ($node->body ? '<div class="content">'. check_output($node->body, $node->format) .'</div></div>' : '</div>'); |
| 406 | |
| 407 | $node->readmore = (strlen($node->teaser) < strlen($node->body)); |
| 408 | |
| 409 | return $node; |
| 410 | } |
| 411 | |
| 412 | /** |
| 413 | * Prepares an event for viewing. |
| 414 | * |
| 415 | * @ingroup event_node |
| 416 | * @param &$node the event to be prepared |
| 417 | * @param $main whether or not the main page is requesting the node |
| 418 | * @param $page whether or not the event is being viewed by itself |
| 419 | * @return a string containing the event after it has been passed through the theme subsystem |
| 420 | */ |
| 421 | function event_view(&$node, $main = 0, $page = 0) { |
| 422 | $node = event_content($node, $main); |
| 423 | if ($page) { |
| 424 | // Breadcrumb navigation |
| 425 | $breadcrumb[] = l(t('Home'), NULL); |
| 426 | $breadcrumb[] = l(t('Events'), 'event'); |
| 427 | drupal_set_breadcrumb($breadcrumb); |
| 428 | } |
| 429 | return theme('node', $node, $main, $page); |
| 430 | } |
| 431 | |
| 432 | /** |
| 433 | * Constructs the start time select boxes. |
| 434 | * |
| 435 | * @param $timestamp The time already selected. This is applicable if the user is editing an event. |
| 436 | * @param $prefix |
| 437 | * @return A set of select boxes that contain options for month, day, year, hour, and minute |
| 438 | * @todo Make the years automatically populated instead of static. |
| 439 | */ |
| 440 | function event_form_date($timestamp, $prefix = '') { |
| 441 | |
| 442 | //determine settings for form's hour selector |
| 443 | if (variable_get('event_ampm', '0')) { |
| 444 | $hour_format = t('g'); |
| 445 | $first_hour = 1; |
| 446 | $last_hour = 12; |
| 447 | } |
| 448 | else { |
| 449 | $hour_format = t('H'); |
| 450 | $first_hour = 0; |
| 451 | $last_hour = 23; |
| 452 | } |
| 453 | |
| 454 | $years = array(2000 => 2000, 2001 => 2001, 2002 => 2002, 2003 => 2003, 2004 => 2004, 2005 => 2005, 2006 => 2006, 2007 => 2007, 2008 => 2008, 2009 => 2009); |
| 455 | $months = array(1 => t('January'), t('February'), t('March'), t('April'), t('May'), t('June'), t('July'), t('August'), t('September'), t('October'), t('November'), t('December')); |
| 456 | for ($i = 1; $i <= 31; $i++) $days[$i] = $i; |
| 457 | for ($i = $first_hour; $i <= $last_hour; $i++) $hours[$i] = $i; |
| 458 | for ($i = 0; $i <= 59; $i++) $minutes[$i] = $i < 10 ? "0$i" : $i; |
| 459 | $am_pms = array('am' => t('am'), 'pm' => t('pm')); |
| 460 | |
| 461 | if ($timestamp) { |
| 462 | // Use event_format_date(), it handles user timezone and locale. |
| 463 | $year = event_format_date($timestamp, 'custom', 'Y'); |
| 464 | $month = event_format_date($timestamp, 'custom', 'm'); |
| 465 | $day = event_format_date($timestamp, 'custom', 'd'); |
| 466 | $hour = event_format_date($timestamp, 'custom', $hour_format); |
| 467 | $minute = event_format_date($timestamp, 'custom', 'i'); |
| 468 | $am_pm = event_format_date($timestamp, 'custom', 'a'); |
| 469 | } |
| 470 | |
| 471 | $when = '<div class="container-inline">'; |
| 472 | $when .= '<div class="day">'; |
| 473 | $when .= form_select('', $prefix .'month', $month, $months); |
| 474 | $when .= form_select('', $prefix .'day', $day, $days); |
| 475 | $when .= form_select('', $prefix .'year', $year, $years); |
| 476 | $when .= '</div><div class="time">'; |
| 477 | $when .= form_select('', $prefix .'hour', $hour, $hours); |
| 478 | $when .= ':'; |
| 479 | $when .= form_select('', $prefix .'minute', $minute, $minutes); |
| 480 | if (variable_get('event_ampm', '0')) { |
| 481 | $when .= form_select('', $prefix .'ampm', $am_pm, $am_pms); |
| 482 | } |
| 483 | $when .= '</div></div>'; |
| 484 | |
| 485 | return $when; |
| 486 | } |
| 487 | |
| 488 | /** |
| 489 | * Prepares the event editing page. |
| 490 | * |
| 491 | * @ingroup event_node |
| 492 | * @param &$node The event to be edited. |
| 493 | * @param &$error Any error messages that need to be displayed. These are returned from event_validate(). |
| 494 | * @return The form elements needed to edit the event. |
| 495 | */ |
| 496 | function event_form(&$node, &$error) { |
| 497 | |
| 498 | $output = ''; |
| 499 | if (module_exist('taxonomy')) { |
| 500 | $output .= implode('', taxonomy_node_form('event', $node)); |
| 501 | } |
| 502 | $output .= form_item(t('Start'), event_form_date($node->start, 'start_'), t('When is this event taking place.')); |
| 503 | $output .= form_item(t('End'), event_form_date($node->end, 'end_'), t('Scheduled end time. If you do not wish to display and end time for this event, do not adjust this time.')); |
| 504 | $fields = event_fields(); |
| 505 | foreach ($fields as $field => $def) { |
| 506 | $function = "form_$def[0]"; |
| 507 | $output .= $function($def[1], $field, $node->$field, $def[7], $def[8], $def[9], NULL, $def[2]); |
| 508 | } |
| 509 | $output .= form_textarea(t('Details'), 'body', $node->body, 60, 15, '', NULL, TRUE); |
| 510 | $output .= filter_form('format', $node->format); |
| 511 | |
| 512 | return $output; |
| 513 | } |
| 514 | |
| 515 | /** |
| 516 | * Creates a query to either insert or update an event in the database. |
| 517 | * |
| 518 | * @param $fields The fields to be retrieved. |
| 519 | * @param $node The node we are inserting or updating. |
| 520 | * @param &$v |
| 521 | * @param $insert Whether or not this is an insert query. |
| 522 | * @return The SQL statement generated by the above criteria. |
| 523 | */ |
| 524 | function event_create_query($fields, $node, &$v, $insert = 1) { |
| 525 | $node->data = array(); |
| 526 | $extra_fields = event_fields(); |
| 527 | foreach ($extra_fields as $field => $def) { |
| 528 | if (isset($node->$field)) { |
| 529 | if ($def[3]) { // Store in separate database field |
| 530 | $fields[] = $field; |
| 531 | } |
| 532 | else { |
| 533 | $node->data[$field] = $node->$field; |
| 534 | } |
| 535 | } |
| 536 | } |
| 537 | $node->data = serialize($node->data); |
| 538 | |
| 539 | foreach ($fields as $field) { |
| 540 | if ($insert) { |
| 541 | $k[] = check_query($field); |
| 542 | $s[] = "'%s'"; |
| 543 | } |
| 544 | else { |
| 545 | $q[] = check_query($field) ." = '%s'"; |
| 546 | } |
| 547 | $v[] = $node->$field; |
| 548 | } |
| 549 | |
| 550 | if ($insert) { |
| 551 | return "INSERT INTO {event} (". implode(", ", $k) .") VALUES(". implode(", ", $s) .")"; |
| 552 | } |
| 553 | else { |
| 554 | return "UPDATE {event} SET ". implode(", ", $q) ." WHERE nid = '$node->nid'"; |
| 555 | } |
| 556 | } |
| 557 | |
| 558 | /** |
| 559 | * Updates the event database table when event nodes are inserted. |
| 560 | * |
| 561 | * @ingroup event_node |
| 562 | * @param @$node The node that is being inserted. |
| 563 | */ |
| 564 | function event_insert(&$node) { |
| 565 | $fields = array('nid', 'start', 'end', 'data'); |
| 566 | $sql = event_create_query($fields, $node, $values); |
| 567 | foreach ($values as $value) { |
| 568 | $vals[] = is_array($value) ? serialize($value) : $value; |
| 569 | } |
| 570 | db_query($sql, $vals); |
| 571 | } |
| 572 | |
| 573 | /** |
| 574 | * Updates the event database table when event nodes are updated. |
| 575 | * |
| 576 | * @ingroup event_node |
| 577 | * @param &$node The node that is being updated. |
| 578 | */ |
| 579 | function event_update(&$node) { |
| 580 | $fields = array('start', 'end', 'data'); |
| 581 | $sql = event_create_query($fields, $node, $values, 0); |
| 582 | foreach ($values as $value) { |
| 583 | $vals[] = is_array($value) ? serialize($value) : $value; |
| 584 | } |
| 585 | db_query($sql, $vals); |
| 586 | } |
| 587 | |
| 588 | /** |
| 589 | * Deletes rows from the event database table when event nodes are deleted. |
| 590 | * |
| 591 | * @ingroup event_node |
| 592 | * @param &$node The node that is being deleted. |
| 593 | */ |
| 594 | function event_delete(&$node) { |
| 595 | db_query("DELETE FROM {event} WHERE nid = %d", $node->nid); |
| 596 | } |
| 597 | |
| 598 | /** |
| 599 | * Loads all of the event-specific information when an event node is viewed. |
| 600 | * |
| 601 | * @ingroup event_node |
| 602 | * @param &$node The node being viewed. |
| 603 | * @return An array of event-specific information. |
| 604 | */ |
| 605 | function event_load(&$node) { |
| 606 | $event = db_fetch_object(db_query("SELECT * FROM {event} WHERE nid = %d", $node->nid)); |
| 607 | $extra_fields = event_fields(); |
| 608 | foreach ($extra_fields as $field => $def) { |
| 609 | if ($def[3]) { // Stored in separate database field |
| 610 | if ($def[0] == "select" && $def[10]) { // multi-select |
| 611 | $event->$field = unserialize($event->$field); |
| 612 | } |
| 613 | } |
| 614 | } |
| 615 | $event->data = unserialize($event->data); |
| 616 | if (is_array($event->data)) { |
| 617 | foreach ($event->data as $field => $value) { |
| 618 | $event->$field = $value; |
| 619 | } |
| 620 | } |
| 621 | return $event; |
| 622 | } |
| 623 | |
| 624 | /** |
| 625 | * @defgroup event_support Support functions to accomplish event-specific tasks. |
| 626 | */ |
| 627 | |
| 628 | /** |
| 629 | * Creates a list of events that are occurring on a given year, month, and day. |
| 630 | * |
| 631 | * @ingroup event_support |
| 632 | * @param $year The year the event is taking place. |
| 633 | * @param $month The month the event is taking place. |
| 634 | * @param $day The day the event is taking place. |
| 635 | * @return An array containing all of the events taking place on the specified date, or an empty array if none exist. |
| 636 | */ |
| 637 | function event_calendar_data($year, $month, $day) { |
| 638 | static $data; |
| 639 | if (!is_array($data[$year][$month])) { |
| 640 | global $user; |
| 641 | $data[$year][$month] = array(); |
| 642 | $days = _event_date('j', _event_mktime(0, 0, 0, $month + 1, 0, $year)); |
| 643 | $first = _event_mktime(0, 0, 0, $month, 1, $year); |
| 644 | $last = _event_mktime(23, 59, 59, $month, $days, $year); |
| 645 | if (variable_get('event_timezone', '1')) { |
| 646 | $first += $user->timezone; |
| 647 | $last += $user->timezone; |
| 648 | } |
| 649 | |
| 650 | $result = db_query('SELECT DISTINCT(n.nid), e.start FROM {event} e INNER JOIN {node} n USING (nid) '. node_access_join_sql() .' WHERE '. node_access_where_sql() .' AND n.status = 1 AND e.start > %d AND e.start < %d ORDER BY e.start', $first, $last); |
| 651 | while ($node = db_fetch_object($result)) { |
| 652 | unset($node->start); // we need to select e.start for pgsql's sake but it confuses node_load. |
| 653 | $node = node_load($node); |
| 654 | $data[$year][$month][event_format_date($node->start, 'custom', 'j')][] = $node; |
| 655 | } |
| 656 | } |
| 657 | |
| 658 | return $data[$year][$month][$day] ? $data[$year][$month][$day] : array(); |
| 659 | } |
| 660 | |
| 661 | /** |
| 662 | * Creates a list of events that are occurring on a given year, month, and day. |
| 663 | * |
| 664 | * @ingroup event_support |
| 665 | * @param $year The year the event is taking place. |
| 666 | * @param $month The month the event is taking place. |
| 667 | * @param $day The day the event is taking place. |
| 668 | * @return An array containing a title parameter for events taking place on the specified date, or an empty array if none exist. |
| 669 | */ |
| 670 | function event_calendar_data_title($year, $month, $day) { |
| 671 | static $data; |
| 672 | if (!is_array($data[$year][$month])) { |
| 673 | global $user; |
| 674 | $data[$year][$month] = array(); |
| 675 | $days = _event_date('j', _event_mktime(0, 0, 0, $month + 1, 0, $year)); |
| 676 | $first = _event_mktime(0, 0, 0, $month, 1, $year); |
| 677 | $last = _event_mktime(23, 59, 59, $month, $days, $year); |
| 678 | if (variable_get('event_timezone', '1')) { |
| 679 | $first += $user->timezone; |
| 680 | $last += $user->timezone; |
| 681 | } |
| 682 | $result = db_query('SELECT DISTINCT(n.nid), n.title, e.start FROM {event} e INNER JOIN {node} n USING (nid) '. node_access_join_sql() .' WHERE '. node_access_where_sql() .' AND n.status = 1 AND e.start > %d AND e.start < %d ORDER BY e.start', $first, $last); |
| 683 | while ($node = db_fetch_object($result)) { |
| 684 | $data[$year][$month][event_format_date($node->start, 'custom', 'j')] = $node; |
| 685 | } |
| 686 | } |
| 687 | if ($data[$year][$month][$day]) { |
| 688 | $title = array(); |
| 689 | $node = $data[$year][$month][$day]; |
| 690 | $title[] = event_format_date($node->start, 'custom', 'H:i') .": ". $node->title; |
| 691 | if (module_exist('over_text')) { |
| 692 | $params = over_text_make(event_format_date($node->start, 'custom', 'l F jS'), join(" | ", $title)); |
| 693 | } |
| 694 | else { |
| 695 | $params["title"] = join(" | ", $title); |
| 696 | } |
| 697 | return $params; |
| 698 | } |
| 699 | else { |
| 700 | return false; |
| 701 | } |
| 702 | } |
| 703 | |
| 704 | /** |
| 705 | * Creates an abbreviated calendar of events. |
| 706 | * |
| 707 | * @ingroup event_support |
| 708 | * @param $year The year the event is taking place. |
| 709 | * @param $month The month the event is taking place. |
| 710 | * @param $day The day the event is taking place. |
| 711 | * @param $timestamp Unused in this method. |
| 712 | * @return A link to a page containing more details about events occurring on the given date, or if no events are |
| 713 | * taking place just the plaintext $day. |
| 714 | */ |
| 715 | function event_calendar_simple($year, $month, $day, $timestamp) { |
| 716 | return count(event_calendar_data($year, $month, $day)) ? l($day, "event/$year/$month/$day", event_calendar_data_title($year, $month, $day)) : $day; |
| 717 | } |
| 718 | |
| 719 | /** |
| 720 | * Creates a detailed calendar of events. |
| 721 | * |
| 722 | * @ingroup event_support |
| 723 | * @param $year The year the event is taking place. |
| 724 | * @param $month The month the event is taking place. |
| 725 | * @param $day The day the event is taking place. |
| 726 | * @param $timestamp Unused in this function. |
| 727 | * @return A string containing all of the events taking place. |
| 728 | */ |
| 729 | function event_calendar_expanded($year, $month, $day, $timestamp) { |
| 730 | |
| 731 | if (variable_get('event_ampm', '0')) { |
| 732 | $date_format = t('g:ia'); |
| 733 | } |
| 734 | else { |
| 735 | $date_format = t('G:i'); |
| 736 | } |
| 737 | |
| 738 | $fields = event_fields(); |
| 739 | $output = "<div class=\"day\">$day</div>\n"; |
| 740 | if (count($data = event_calendar_data($year, $month, $day))) { |
| 741 | foreach ($data as $node) { |
| 742 | $output .= '<div class="event">'; |
| 743 | $output .= '<span class="time">'. event_format_date($node->start, 'custom', $date_format) .'</span>'; |
| 744 | $output .= '<span class="title">'. l($node->title, "node/$node->nid") .'</span>'; |
| 745 | foreach ($fields as $field => $def) { |
| 746 | if ($def[4] && $node->$field) { |
| 747 | if ($node->$field) { |
| 748 | $output .= "<span class=\"$field\">"; |
| 749 | if ($def[0] == "select") { |
| 750 | if ($def[10]) { // multi-select |
| 751 | foreach ($node->$field as $val) { |
| 752 | $vals[] = $def[7][$val]; |
| 753 | } |
| 754 | $output .= implode(", ", $vals); |
| 755 | } |
| 756 | else { |
| 757 | $output .= $def[7][$node->$field]; |
| 758 | } |
| 759 | } |
| 760 | else { |
| 761 | $output .= $node->$field; |
| 762 | } |
| 763 | $output .= '</span>'; |
| 764 | } |
| 765 | } |
| 766 | } |
| 767 | $output .= '</div>'; |
| 768 | } |
| 769 | } |
| 770 | else { |
| 771 | $output .= '<div class="event-empty"></div>'; |
| 772 | } |
| 773 | return $output; |
| 774 | } |
| 775 | |
| 776 | /** |
| 777 | * Creates the graphical calendar and table views for events. |
| 778 | * |
| 779 | * @ingroup event_support |
| 780 | * @param $callback |
| 781 | * @param &$year The year the event is taking place. |
| 782 | * @param &$month The month the event is taking place. |
| 783 | * @param &$day The day the event is taking place. |
| 784 | * @param $navigation |
| 785 | * @param $extra |
| 786 | * @return The fully formatted calendar or table. |
| 787 | */ |
| 788 | function event_display($callback, &$year, &$month, &$day, $navigation = 0, $extra = 0) { |
| 789 | global $user; |
| 790 | $time = time(); |
| 791 | if (variable_get('event_timezone', '1')) { |
| 792 | $time += $user->timezone; |
| 793 | } |
| 794 | if (!$year) { |
| 795 | $year = _event_date('Y', $time); |
| 796 | } |
| 797 | if (!$month) { |
| 798 | $month = _event_date('m', $time); |
| 799 | } |
| 800 | |
| 801 | // Sanitize date: |
| 802 | $eom = _event_mktime(0, 0, 0, $month + 1, 0, $year); |
| 803 | $days = _event_date('j', $eom); |
| 804 | $date = _event_mktime(0, 0, 0, $month, ($day && $day <= $days ? $day : 1), $year); |
| 805 | $today = _event_mktime(0, 0, 0, _event_date('m', $time), _event_date('j', $time), _event_date('Y', $time)); |
| 806 | |
| 807 | // Extract key data from date: |
| 808 | $month_name = _event_date('M', $date); // do not translate, used only for css |
| 809 | $weeks = ceil($days / 7); |
| 810 | |
| 811 | // Initialize the header/week days: |
| 812 | if (variable_get('event_start_min', 0) < $date) { |
| 813 | // $prev = '<span class="prev">'. l('«', 'event/'. ($month - 1 < 1 ? $year - 1 .'/12' : "$year/". ($month - 1)) . ($day ? "/$day" : '')) .'</span>'; |
| 814 | $prev = '<span class="prev">'. l('«', 'event/'. ($month - 1 < 1 ? $year - 1 .'/12' : "$year/". ($month - 1))) .'</span>'; |
| 815 | } |
| 816 | else { |
| 817 | $prev = '<span class="prev"> </span>'; |
| 818 | } |
| 819 | if (variable_get('event_start_max', 10000000000) > $eom) { |
| 820 | // $next = '<span class="next">'. l('»', 'event/'. ($month + 1 > 12 ? $year + 1 .'/1' : "$year/". ($month + 1)) . ($day ? "/$day" : '')) .'</span>'; |
| 821 | $next = '<span class="next">'. l('»', 'event/'. ($month + 1 > 12 ? $year + 1 .'/1' : "$year/". ($month + 1))) .'</span>'; |
| 822 | } |
| 823 | else { |
| 824 | $next = '<span class="next"> </span>'; |
| 825 | } |
| 826 | if (!$navigation) { |
| 827 | $name = l(t(_event_date('F', $date)) .' '. _event_date('Y', $date), 'event/'. ("$year/". ($month))); |
| 828 | } |
| 829 | else { |
| 830 | $name = t(_event_date('F', $date)) .' '. _event_date('Y', $date); |
| 831 | } |
| 832 | $header = array( |
| 833 | array('class' => 'prev', 'data' => $prev), |
| 834 | array('class' => 'heading', 'colspan' => 5, 'data' => $name), |
| 835 | array('class' => 'next', 'data' => $next) |
| 836 | ); |
| 837 | |
| 838 | if (!$extra) { // calendar views |
| 839 | $day_name = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'); |
| 840 | $day_trans = array(t('Sun'), t('Mon'), t('Tue'), t('Wed'), t('Thu'), t('Fri'), t('Sat')); |
| 841 | $weekstart = variable_get('date_first_day', 0); |
| 842 | |
| 843 | // Week starts when? |
| 844 | $day_name = array_merge(array_slice($day_name, $weekstart), array_slice($day_name, 0, $weekstart)); |
| 845 | $day_trans = array_merge(array_slice($day_trans, $weekstart), array_slice($day_trans, 0, $weekstart)); |
| 846 | |
| 847 | foreach ($day_name as $key => $_day) { |
| 848 | $row[] = array('class' => strtolower("days $_day"), 'data' => $day_trans[$key]); |
| 849 | } |
| 850 | $rows = array($row); |
| 851 | $week = 1; |
| 852 | |
| 853 | // Create table days. |
| 854 | $row = array_fill(0, 6, ''); |
| 855 | for ($_day = 1; $_day <= $days; $_day++) { |
| 856 | $timestamp = _event_mktime(0, 0, 0, $month, $_day, $year); |
| 857 | // Make sure we have the right day (week starts on). |
| 858 | $week_day = (_event_date('w', $timestamp) - $weekstart + 7) % 7; |
| 859 | $row[$week_day] = array( |
| 860 | 'class' => strtolower("$month_name $day_name[$week_day]". ($weeks == $week ? ' lastweek' : '') . ($timestamp == $today ? ' today' : '') . ($_day == $day ? ' selected' : '')), |
| 861 | 'id' => strtolower($month_name . $_day), |
| 862 | 'data' => $callback($year, $month, $_day, $timestamp) |
| 863 | ); |
| 864 | |
| 865 | if ($week_day == 6 || $_day == $days) { |
| 866 | $rows[] = array_pad($row, 7, ' '); |
| 867 | $row = array(); |
| 868 | $week++; |
| 869 | } |
| 870 | } |
| 871 | $output = '<div class="event-calendar">'; |
| 872 | $output .= theme("table", $header, $rows); |
| 873 | } |
| 874 | else { // table view |
| 875 | $start = _event_mktime(0, 0, 0, $month, ($day ? $day : 1), $year); |
| 876 | $days = _event_date('j', _event_mktime(0, 0, 0, $month + 1, 0, $year)); |
| 877 | $last = _event_mktime(23, 59, 59, $month, $days, $year); |
| 878 | if (variable_get('event_timezone', '1')) { |
| 879 | $start += $user->timezone; |
| 880 | $last += $user->timezone; |
| 881 | } |
| 882 | $output = '<div class="event-calendar">'; |
| 883 | $output .= theme('table', $header, NULL); |
| 884 | $output .= $callback($start, $last, $today); |
| 885 | } |
| 886 | |
| 887 | $output .= '</div>'; |
| 888 | |
| 889 | return $output; |
| 890 | } |
| 891 | |
| 892 | /** |
| 893 | * Creates a themed table of events. |
| 894 | * |
| 895 | * @ingroup event_support |
| 896 | * @param $start The starting date for the table. |
| 897 | * @param $month The ending date for the table. |
| 898 | * @param $today The date to be indicated as current in the table. |
| 899 | * @return A fully themed table. |
| 900 | */ |
| 901 | function event_table($start, $end, $today) { |
| 902 | $extra = event_fields(); |
| 903 | $headerarray = $type = array(); |
| 904 | foreach($extra as $key => $def) { |
| 905 | if ($def[3]) { |
| 906 | $headerarray[$def[1]] = 'e.'. $key; |
| 907 | $type['e.'. $key]['type'] = $def[0]; |
| 908 | $type['e.'. $key]['fields'] = $def[7]; |
| 909 | } |
| 910 | } |
| 911 | $headerkeys = variable_get('event_table_headers', array('e.start', 'n.title', 'n.teaser')); |
| 912 | $headerarray = array_merge(array(t('Date') => 'e.start', t('Title') => 'n.title', t('Teaser') => 'n.teaser', t('Body') => 'n.body'), $headerarray); |
| 913 | $type = array_merge(array('e.start' => array('type' => 'time'), 'n.title' => array('type' => 'textfield'), 'n.teaser' => array('type' => 'textarea'), 'n.body' => array('type' => 'textarea')), $type); |
| 914 | $headerarray = array_intersect($headerarray, $headerkeys); |
| 915 | $header = array(); |
| 916 | foreach ($headerarray as $name => $column) { |
| 917 | $header[] = array('data' => $name, 'field' => $column); |
| 918 | } |
| 919 | $sql = 'SELECT n.nid, n.title, n.teaser, n.body, e.* FROM {node} n '. node_access_join_sql() .' INNER JOIN {event} e ON n.nid = e.nid WHERE '. node_access_where_sql() ." AND n.status = 1 AND e.start > $start AND e.start < $end"; |
| 920 | $sql .= tablesort_sql($header); |
| 921 | $result = pager_query($sql, 10); |
| 922 | $rows = array(); |
| 923 | while ($event = db_fetch_object($result)) { |
| 924 | $row = array(); |
| 925 | foreach ($headerarray as $column) { |
| 926 | $field = substr($column, 2); |
| 927 | $row[] = array('data' => event_format_field($type[$column], $event->$field, $field, $event->nid), 'class' => $type[$column]['type'] .' '. $field . (($today == _event_mktime(0, 0, 0, _event_date('m', $event->start), _event_date('j', $event->start), _event_date('Y', $event->start))) ? ' today': '')); |
| 928 | } |
| 929 | $rows[] = $row; |
| 930 | } |
| 931 | if ($pager = theme('pager', NULL, 10, 0, tablesort_pager())) { |
| 932 | $rows[] = array(array('data' => $pager, "colspan" => count($headerfields))); |
| 933 | } |
| 934 | |
| 935 | return theme('table', $header, $rows); |
| 936 | } |
| 937 | |
| 938 | function event_format_field($type, $data, $field, $nid) { |
| 939 | switch ($type['type']) { |
| 940 | case 'textarea': |
| 941 | case 'textfield': |
| 942 | if ($field == 'title') { |
| 943 | return l($data, "node/$nid", array("title" => t('Click here to see the full event.'))); |
| 944 | } |
| 945 | return $data; |
| 946 | break; |
| 947 | case 'time': |
| 948 | return event_format_date($data, 'custom', t('M, j')); |
| 949 | break; |
| 950 | case 'select': |
| 951 | $arr = array(); |
| 952 | foreach (unserialize($data) as $key) { |
| 953 | $arr[] = $type['fields'][$key]; |
| 954 | } |
| 955 | return implode(', ', $arr); |
| 956 | break; |
| 957 | } |
| 958 | } |
| 959 | |
| 960 | /** |
| 961 | * Formats a date for display to the user. |
| 962 | * |
| 963 | * @ingroup event_support |
| 964 | * @param $timestamp The date to be displayed. |
| 965 | * @param $type The format to display the date in. |
| 966 | * @param $format A PHP date format string. This is only applicable if $type is 'custom'. |
| 967 | * @return A string containing the formatted date. |
| 968 | */ |
| 969 | function event_format_date($timestamp, $type = 'medium', $format = '') { |
| 970 | $tz = variable_get('event_timezone', '1') ? NULL : 0; |
| 971 | return format_date($timestamp, $type, $format, $tz); |
| 972 | } |
| 973 | |
| 974 | function _event_date($time, $format) { |
| 975 | return gmdate($time, $format); |
| 976 | } |
| 977 | |
| 978 | function _event_mktime($hour, $minute, $second, $month, $day, $year) { |
| 979 | return gmmktime($hour, $minute, $second, $month, $day, $year); |
| 980 | } |
| 981 | |
| 982 | /** |
| 983 | * Creates a page that the user may use to search for events. |
| 984 | * |
| 985 | * @ingroup event_support |
| 986 | * @return A string containing the search form and any results returned. |
| 987 | */ |
| 988 | function event_query() { |
| 989 | $output = event_query_form(); |
| 990 | switch ($_POST['op']) { |
| 991 | case t('Search'): |
| 992 | $result = event_query_parse((object) $_POST['edit']); |
| 993 | if (db_num_rows($result)) { |
| 994 | $output .= theme('event_query_results', $result); |
| 995 | } |
| 996 | else { |
| 997 | drupal_set_message(t('No matches found.')); |
| 998 | } |
| 999 | break; |
| 1000 | } |
| 1001 | return $output; |
| 1002 | } |
| 1003 | |
| 1004 | function event_query_parse($edit) { |
| 1005 | $fields = event_fields(); |
| 1006 | $query = array('n.status = 1'); |
| 1007 | |
| 1008 | // Calculate timestamps if we have all the parameters. |
| 1009 | if (isset($edit->from['year']) && isset($edit->from['month']) && isset($edit->from['day']) && isset($edit->from['hour']) && isset($edit->from['minute'])) { |
| 1010 | $str = _event_mktime($edit->from['hour'], $edit->from['minute'], 0, $edit->from['month'], $edit->from['day'], $edit->from['year']); |
| 1011 | if (variable_get('event_timezone', '1& |