/** * Find a list of pairs specifying the times the event occurs, for 20 years into the future, in user-time. * * @param ID_TEXT The timezone for the event (NULL: current user's timezone) * @param BINARY Whether the time should be converted to the viewer's own timezone * @param integer The year the event starts at. This and the below are in server time * @param integer The month the event starts at * @param integer The day the event starts at * @param integer The hour the event starts at * @param integer The minute the event starts at * @param ?integer The year the event ends at (NULL: not a multi day event) * @param ?integer The month the event ends at (NULL: not a multi day event) * @param ?integer The day the event ends at (NULL: not a multi day event) * @param ?integer The hour the event ends at (NULL: not a multi day event / all day event) * @param ?integer The minute the event ends at (NULL: not a multi day event / all day event) * @param string The event recurrence * @param ?integer The number of recurrences (NULL: none/infinite) * @param ?TIME The timestamp that found times must exceed. In user-time (NULL: now) * @param ?TIME The timestamp that found times must not exceed. In user-time (NULL: 20 years time) * @return array A list of pairs for period times (timestamps, in user-time). Actually a series of pairs, 'window-bound timestamps' is first pair, then 'true coverage timestamps', then 'true coverage timestamps without timezone conversions' */ function find_periods_recurrence($timezone, $do_timezone_conv, $start_year, $start_month, $start_day, $start_hour, $start_minute, $end_year, $end_month, $end_day, $end_hour, $end_minute, $recurrence, $recurrences, $period_start = NULL, $period_end = NULL) { if ($recurrences === 0) { return array(); } if (is_null($period_start)) { $period_start = utctime_to_usertime(time()); } if (is_null($period_end)) { $period_end = utctime_to_usertime(time() + 60 * 60 * 24 * 360 * 20); } $times = array(); $i = 0; $parts = explode(' ', $recurrence); if (count($parts) != 1) { $recurrence = $parts[0]; $mask = $parts[1]; $mask_len = strlen($mask); } else { $mask = '1'; $mask_len = 1; } $a = 0; $dif_day = 0; $dif_month = 0; $dif_year = 0; $dif = utctime_to_usertime() - utctime_to_usertime(mktime($start_hour, $start_minute, 0, $start_month, $start_day, $start_year)); switch ($recurrence) { case 'daily': $dif_day = 1; if ($dif > 60 * 60 * 24 * 10 && $mask_len == 0) { $zoom = $dif_day * intval(floor(floatval($dif) / (60.0 * 60.0 * 24.0))); $start_day += $zoom; if (!is_null($end_day)) { $end_day += $zoom; } } break; case 'weekly': $dif_day = 7; if ($dif > 60 * 60 * 24 * 70 && $mask_len == 0) { $zoom = $dif_day * intval(floor(floatval($dif) / (60.0 * 60.0 * 24.0))) - 70; $start_day += $zoom; if (!is_null($end_day)) { $end_day += $zoom; } } break; case 'monthly': $dif_month = 1; if ($dif > 60 * 60 * 24 * 31 * 10 && $mask_len == 0) { $zoom = $dif_month * intval(floor(floatval($dif) / (60.0 * 60.0 * 24.0 * 31.0))) - 10; $start_month += $zoom; if (!is_null($end_day)) { $end_day += $zoom; } } break; case 'yearly': $dif_year = 1; if ($dif > 60 * 60 * 24 * 365 * 10 && $mask_len == 0) { $zoom = $dif_year * intval(floor(floatval($dif) / (60.0 * 60.0 * 24.0 * 365.0))) - 1; $start_year += $zoom; if (!is_null($end_day)) { $end_day += $zoom; } } break; } $_b = mixed(); $b = mixed(); do { /* Consider this scenario... An event ends at end of 1/1/2012 (23:59), which is 22:59 in UTC if they are in +1 timezone Therefore the event, which is stored in UTC, needs a server time of 22:59 before going through cal_utctime_to_usertime The server already has the day stored UTC which may be different to the day stored for the +1 timezone (in fact either the start or end day will be stored differently, assuming there is an end day) */ $_a = cal_get_start_utctime_for_event($timezone, $start_year, $start_month, $start_day, $start_hour, $start_minute, $do_timezone_conv == 1); $a = cal_utctime_to_usertime($_a, $timezone, $do_timezone_conv == 1); if (is_null($start_hour) && (is_null($end_year) || is_null($end_month) || is_null($end_day))) { // Should not be needed, but normalise possible database error $start_minute = NULL; $start_hour = NULL; $end_minute = NULL; $end_hour = NULL; $end_day = $start_day; $end_month = $start_month; $end_year = $start_year; } if (is_null($end_year) || is_null($end_month) || is_null($end_day)) { $_b = NULL; $b = NULL; } else { $_b = cal_get_end_utctime_for_event($timezone, $end_year, $end_month, $end_day, $end_hour, $end_minute, $do_timezone_conv == 1); $b = cal_utctime_to_usertime($_b, $timezone, $do_timezone_conv == 1); } $starts_within = $a >= $period_start && $a < $period_end; $ends_within = $b > $period_start && $b <= $period_end; $spans = $a < $period_start && $b > $period_end; if (($starts_within || $ends_within || $spans) && in_array($mask[$i % $mask_len], array('1', 'y'))) { $times[] = array(max($period_start, $a), min($period_end, $b), $a, $b, $_a, $_b); } $i++; $start_day += $dif_day; $start_month += $dif_month; $start_year += $dif_year; if (!is_null($end_year) && !is_null($end_month) && !is_null($end_day)) { $end_day += $dif_day; $end_month += $dif_month; $end_year += $dif_year; } if ($i == 300) { break; } // Let's be reasonable } while ($recurrence != '' && $recurrence != 'none' && $a < $period_end && (is_null($recurrences) || $i < $recurrences)); return $times; }
/** * Subscribe for reminders to an event. * * @return tempcode The UI */ function _subscribe_event() { $title = get_page_title('SUBSCRIBE_EVENT'); $seconds_before = intval(floatval(post_param('hours_before')) * 3600.0); $id = get_param_integer('id'); // The event ID $events = $GLOBALS['SITE_DB']->query_select('calendar_events', array('*'), array('id' => get_param_integer('id')), '', 1); $event = $events[0]; $rem_id = $GLOBALS['SITE_DB']->query_insert('calendar_reminders', array('e_id' => $id, 'n_member_id' => get_member(), 'n_seconds_before' => $seconds_before), true); if (has_actual_page_access($GLOBALS['FORUM_DRIVER']->get_guest_id(), 'calendar') && has_category_access($GLOBALS['FORUM_DRIVER']->get_guest_id(), 'calendar', strval($event['e_type']))) { $_from = cal_get_start_utctime_for_event($event['e_timezone'], $event['e_start_year'], $event['e_start_month'], $event['e_start_day'], $event['e_start_hour'], $event['e_start_minute'], $event['e_do_timezone_conv'] == 1); $from = cal_utctime_to_usertime($_from, $event['e_timezone'], $event['e_do_timezone_conv'] == 1); $to = mixed(); if (!is_null($event['e_end_year']) && !is_null($event['e_end_month']) && !is_null($event['e_end_day'])) { $_to = cal_get_end_utctime_for_event($event['e_timezone'], $event['e_end_year'], $event['e_end_month'], $event['e_end_day'], $event['e_end_hour'], $event['e_end_minute'], $event['e_do_timezone_conv'] == 1); $to = cal_utctime_to_usertime($_to, $event['e_timezone'], $event['e_do_timezone_conv'] == 1); } syndicate_described_activity('calendar:ACTIVITY_SUBSCRIBED_EVENT', get_translated_text($event['e_title']), date_range($from, $to, !is_null($event['e_start_hour'])), '', '_SEARCH:calendar:view:' . strval($id), '', '', 'calendar', 1, NULL, true); } // Add next reminder to job system $recurrences = find_periods_recurrence($event['e_timezone'], 1, $event['e_start_year'], $event['e_start_month'], $event['e_start_day'], is_null($event['e_start_hour']) ? 0 : $event['e_start_hour'], is_null($event['e_start_minute']) ? 0 : $event['e_start_minute'], $event['e_end_year'], $event['e_end_month'], $event['e_end_day'], is_null($event['e_end_hour']) ? 0 : $event['e_end_hour'], is_null($event['e_end_minute']) ? 0 : $event['e_end_minute'], $event['e_recurrence'], min(1, $event['e_recurrences'])); if (array_key_exists(0, $recurrences)) { $GLOBALS['SITE_DB']->query_insert('calendar_jobs', array('j_time' => usertime_to_utctime($recurrences[0][0]) - $seconds_before, 'j_reminder_id' => $rem_id, 'j_member_id' => get_member(), 'j_event_id' => get_param_integer('id'))); } $url = build_url(array('page' => '_SELF', 'type' => 'view', 'id' => get_param_integer('id')), '_SELF'); return redirect_screen($title, $url, do_lang_tempcode('SUCCESS')); }
/** * Standard aed_module edit actualiser. * * @param ID_TEXT The entry being edited * @return tempcode Description shown after editing */ function edit_actualisation($_id) { $id = intval($_id); $rows = $GLOBALS['SITE_DB']->query_select('calendar_events', array('*'), array('id' => $id), '', 1); if (!array_key_exists(0, $rows)) { warn_exit(do_lang_tempcode('MISSING_RESOURCE')); } $event = $rows[0]; check_edit_permission($event['e_is_public'] == 1 ? 'mid' : 'low', $event['e_submitter']); $delete_status = post_param('delete', '0'); list($type, $recurrence, $_recurrences, $title, $content, $priority, $is_public, $_start_year, $_start_month, $_start_day, $_start_hour, $_start_minute, $_end_year, $_end_month, $_end_day, $_end_hour, $_end_minute, $timezone, $do_timezone_conv) = $this->get_event_parameters(); $allow_trackbacks = post_param_integer('allow_trackbacks', fractional_edit() ? INTEGER_MAGIC_NULL : 0); $allow_rating = post_param_integer('allow_rating', fractional_edit() ? INTEGER_MAGIC_NULL : 0); $allow_comments = post_param_integer('allow_comments', fractional_edit() ? INTEGER_MAGIC_NULL : 0); $notes = post_param('notes', STRING_MAGIC_NULL); $validated = post_param_integer('validated', fractional_edit() ? INTEGER_MAGIC_NULL : 0); $seg_recurrences = post_param_integer('seg_recurrences', fractional_edit() ? INTEGER_MAGIC_NULL : 0); $fixed_past = false; if ($delete_status == '3' && !fractional_edit()) { // Fix past occurences $past_times = find_periods_recurrence($event['e_timezone'], 1, $event['e_start_year'], $event['e_start_month'], $event['e_start_day'], $event['e_start_hour'], $event['e_start_minute'], $event['e_end_year'], $event['e_end_month'], $event['e_end_day'], $event['e_end_hour'], $event['e_end_minute'], $event['e_recurrence'], $event['e_recurrences'], utctime_to_usertime(mktime($event['e_start_hour'], $event['e_start_minute'], 0, $event['e_start_month'], $event['e_start_day'], $event['e_start_year'])), utctime_to_usertime(time())); if (count($past_times) > 0) { foreach ($past_times as $past_time) { list($start_year, $start_month, $start_day, $start_hour, $start_minute) = explode('-', date('Y-m-d-h-i', usertime_to_utctime($past_time[0]))); if (is_null($past_time[1])) { list($end_year, $end_month, $end_day, $end_hour, $end_minute) = array(NULL, NULL, NULL, NULL, NULL); } else { $explode = explode('-', date('Y-m-d-h-i', usertime_to_utctime($past_time[1]))); $end_year = intval($explode[0]); $end_month = intval($explode[1]); $end_day = intval($explode[2]); $end_hour = intval($explode[3]); $end_minute = intval($explode[4]); } add_calendar_event($event['e_type'], 'none', NULL, 0, get_translated_text($event['e_title']), get_translated_text($event['e_content']), $event['e_priority'], $event['e_is_public'], intval($start_year), intval($start_month), intval($start_day), intval($start_hour), intval($start_minute), $end_year, $end_month, $end_day, $end_hour, $end_minute, $timezone, $do_timezone_conv, $validated, $allow_rating, $allow_comments, $allow_trackbacks, $notes); } if (is_null($_recurrences)) { $recurrences = NULL; } else { $recurrences = max(0, $_recurrences - count($past_times)); } // Find next occurence in future if (count($past_times) == 0) { $start_year = $_start_year; $start_month = $_start_month; $start_day = $_start_day; $start_hour = $_start_hour; $start_minute = $_start_minute; $end_year = $_end_year; $end_month = $_end_month; $end_day = $_end_day; $end_hour = $_end_hour; $end_minute = $_end_minute; } $past_times = find_periods_recurrence($event['e_timezone'], 1, $start_year, $start_month, $start_day, $start_hour, $start_minute, $end_year, $end_month, $end_day, $end_hour, $end_minute, $event['e_recurrence'], 1, time()); if (array_key_exists(0, $past_times)) { $past_time = $past_times[0]; $explode = explode('-', date('Y-m-d-h-i', $past_time[0])); $start_year = intval($explode[0]); $start_month = intval($explode[1]); $start_day = intval($explode[2]); $start_hour = intval($explode[3]); $start_minute = intval($explode[4]); if (is_null($past_time[1])) { list($end_year, $end_month, $end_day, $end_hour, $end_minute) = array(NULL, NULL, NULL, NULL, NULL); } else { $explode = explode('-', date('Y-m-d-h-i', $past_time[1])); $end_year = intval($explode[0]); $end_month = intval($explode[1]); $end_day = intval($explode[2]); $end_hour = intval($explode[3]); $end_minute = intval($explode[4]); } } else { $recurrences = 0; } $fixed_past = true; } } if (!$fixed_past) { $start_year = $_start_year; $start_month = $_start_month; $start_day = $_start_day; $start_hour = $_start_hour; $start_minute = $_start_minute; $end_year = $_end_year; $end_month = $_end_month; $end_day = $_end_day; $end_hour = $_end_hour; $end_minute = $_end_minute; $recurrences = $_recurrences; } if ($validated == 1 && $GLOBALS['SITE_DB']->query_value('calendar_events', 'validated', array('id' => $id)) == 0) { if (has_actual_page_access($GLOBALS['FORUM_DRIVER']->get_guest_id(), 'calendar') && has_category_access($GLOBALS['FORUM_DRIVER']->get_guest_id(), 'calendar', strval($type))) { $_from = cal_get_start_utctime_for_event($timezone, $start_year, $start_month, $start_day, $start_hour, $start_minute, true); $from = cal_utctime_to_usertime($_from, $timezone, false); $to = mixed(); if (!is_null($end_year) && !is_null($end_month) && !is_null($end_day)) { $_to = cal_get_end_utctime_for_event($timezone, $end_year, $end_month, $end_day, $end_hour, $end_minute, true); $to = cal_utctime_to_usertime($_to, $timezone, false); } $submitter = $GLOBALS['SITE_DB']->query_value('calendar_events', 'e_submitter', array('id' => $id)); syndicate_described_activity($submitter != get_member() ? 'calendar:ACTIVITY_VALIDATE_CALENDAR_EVENT' : 'calendar:ACTIVITY_CALENDAR_EVENT', $title, date_range($from, $to, !is_null($start_hour)), '', '_SEARCH:calendar:view:' . strval($id), '', '', 'calendar', 1, NULL, true); } } edit_calendar_event($id, $type, $recurrence, $recurrences, $seg_recurrences, $title, $content, $priority, $is_public, $start_year, $start_month, $start_day, $start_hour, $start_minute, $end_year, $end_month, $end_day, $end_hour, $end_minute, $timezone, $do_timezone_conv, post_param('meta_keywords', STRING_MAGIC_NULL), post_param('meta_description', STRING_MAGIC_NULL), $validated, $allow_rating, $allow_comments, $allow_trackbacks, $notes); if (!fractional_edit()) { $conflicts = detect_conflicts(get_member(), $id, $start_year, $start_month, $start_day, $start_hour, $start_minute, $end_year, $end_month, $end_day, $end_hour, $end_minute, $recurrence, $recurrences); $_description = is_null($conflicts) ? paragraph(do_lang_tempcode('SUCCESS')) : $conflicts; regenerate_event_reminder_jobs($id); } else { $_description = do_lang_tempcode('SUCCESS'); } $this->donext_type = $type; $this->donext_date = strval($start_year) . '-' . strval($start_month) . '-' . strval($start_day); return $_description; }