/** * 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; }
/** * Detect conflicts with an event in certain time periods. * * @param MEMBER The member to detect conflicts for * @param AUTO_LINK The event ID that we are detecting conflicts with (we need this so we don't think we conflict with ourself) * @param array List of pairs specifying our happening time (in time order) * @param boolean Whether to restrict only to viewable events for the current member * @param ?TIME The timestamp that found times must exceed. In user-time (NULL: use find_periods_recurrence default) * @param ?TIME The timestamp that found times must not exceed. In user-time (NULL: use find_periods_recurrence default) * @return array A list of events happening, with time details */ function detect_happening_at($member_id, $skip_id, $our_times, $restrict = true, $period_start = NULL, $period_end = NULL) { if (count($our_times) == 0) { return array(); } $conflicts = array(); $where = is_null($skip_id) ? '' : 'id<>' . strval($skip_id); if ($restrict) { if ($where != '') { $where .= ' AND '; } $where .= '(e_submitter=' . strval((int) $member_id) . ' OR e_is_public=1)'; } if ($where != '') { $where .= ' AND '; } $where .= '(validated=1 OR e_is_public=0)'; $where .= ' AND (((e_start_month>=' . strval(intval(date('m', $our_times[0][0])) - 1) . ' AND e_start_year=' . date('Y', $our_times[0][0]) . ') AND (e_start_month<=' . strval(intval(date('m', $our_times[0][1])) + 1) . ' AND e_start_year=' . date('Y', $our_times[0][1]) . ' OR e_start_year<' . date('Y', $our_times[0][1]) . ')) OR ' . db_string_not_equal_to('e_recurrence', 'none') . ')'; $where = ' WHERE ' . $where; $table = 'calendar_events e'; $events = $GLOBALS['SITE_DB']->query('SELECT *,e.id AS e_id FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . $table . $where); foreach ($events as $event) { if (!has_category_access(get_member(), 'calendar', strval($event['e_type']))) { continue; } $their_times = 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']) ? find_timezone_start_hour_in_utc($event['e_timezone'], $event['e_start_year'], $event['e_start_month'], $event['e_start_day']) : $event['e_start_hour'], is_null($event['e_start_minute']) ? find_timezone_start_minute_in_utc($event['e_timezone'], $event['e_start_year'], $event['e_start_month'], $event['e_start_day']) : $event['e_start_minute'], $event['e_end_year'], $event['e_end_month'], $event['e_end_day'], is_null($event['e_end_hour']) ? find_timezone_end_hour_in_utc($event['e_timezone'], $event['e_end_year'], $event['e_end_month'], $event['e_end_day']) : $event['e_end_hour'], is_null($event['e_end_minute']) ? find_timezone_end_minute_in_utc($event['e_timezone'], $event['e_end_year'], $event['e_end_month'], $event['e_end_day']) : $event['e_end_minute'], $event['e_recurrence'], $event['e_recurrences'], $period_start, $period_end); // Now search every combination to see if we can get a hit foreach ($our_times as $our) { foreach ($their_times as $their) { $conflict = false; if (is_null($our[3]) && is_null($their[3])) { if ($our[2] == $their[2]) { $conflict = true; } } elseif (is_null($our[3]) && !is_null($their[3])) { if ($our[2] >= $their[2] && $our[2] < $their[3]) { $conflict = true; } } elseif (!is_null($our[3]) && is_null($their[3])) { if ($their[2] >= $our[2] && $their[2] < $our[3]) { $conflict = true; } } elseif (!is_null($our[3]) && !is_null($their[3])) { if ($our[2] >= $their[2] && $our[2] < $their[3]) { $conflict = true; } if ($their[2] >= $our[2] && $their[2] < $our[3]) { $conflict = true; } } if ($conflict) { $conflicts[] = array($event['e_id'], $event, $their[2], $their[3]); break 2; } } } } return $conflicts; }
/** * Standard modular run function for CRON hooks. Searches for tasks to perform. */ function run() { if (!addon_installed('calendar')) { return; } require_code('calendar'); require_lang('calendar'); require_code('notifications'); $start = 0; do { $jobs = $GLOBALS['SITE_DB']->query('SELECT *,j.id AS id FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'calendar_jobs j LEFT JOIN ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'calendar_events e ON e.id=j.j_event_id LEFT JOIN ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'calendar_reminders n ON n.id=j.j_reminder_id WHERE (validated=1 OR e_is_public=0) AND j_time<' . strval(time()), 300, $start); $or_list = ''; foreach ($jobs as $job) { // Build up OR list of the jobs if ($or_list != '') { $or_list .= ' OR '; } $or_list .= 'id=' . strval($job['id']); $recurrences = find_periods_recurrence($job['e_timezone'], 1, $job['e_start_year'], $job['e_start_month'], $job['e_start_day'], is_null($job['e_start_hour']) ? find_timezone_start_hour_in_utc($job['e_timezone'], $job['e_start_year'], $job['e_start_month'], $job['e_start_day']) : $job['e_start_hour'], is_null($job['e_start_minute']) ? find_timezone_start_minute_in_utc($job['e_timezone'], $job['e_start_year'], $job['e_start_month'], $job['e_start_day']) : $job['e_start_minute'], $job['e_end_year'], $job['e_end_month'], $job['e_end_day'], is_null($job['e_end_hour']) ? find_timezone_end_hour_in_utc($job['e_timezone'], $job['e_end_year'], $job['e_end_month'], $job['e_end_day']) : $job['e_end_hour'], is_null($job['e_end_minute']) ? find_timezone_end_minute_in_utc($job['e_timezone'], $job['e_end_year'], $job['e_end_month'], $job['e_end_day']) : $job['e_end_minute'], $job['e_recurrence'], min(1, $job['e_recurrences'])); // Dispatch if (is_null($job['j_reminder_id'])) { // if (!has_actual_page_access($job['e_submitter'],'admin_occle')) continue; // Someone was admin but isn't anymore Actually, really ex-admins could have placed lots of other kinds of traps. It's the responsibility of the staff to check this on a wider basis. There's no use creating tangental management complexity for just one case. if ($job['e_type'] != db_get_first_id()) { continue; } // Very strange $job_text = get_translated_text($job['e_content']); if (substr($job_text, 0, 7) == 'http://') { require_code('character_sets'); echo convert_to_internal_encoding(http_download_file($job_text)); } elseif (addon_installed('occle')) { if (is_null($GLOBALS['CURRENT_SHARE_USER'])) { // Backwards-compatibility for pure PHP code (if its creation date was before the time of writing this comment [Wednesday 22nd Match, 14:58]) if ($job['e_add_date'] < 1143046670 && !defined('HIPHOP_PHP')) { @ini_set('ocproducts.xss_detect', '0'); $to_echo = eval($job_text); if ($to_echo === false) { fatal_exit(@strval($php_errormsg)); } } else { $GLOBALS['event_timestamp'] = array_key_exists(0, $recurrences) ? usertime_to_utctime($recurrences[0][0]) : mktime($job['e_start_hour'], $job['e_start_minute'], 0, $job['e_start_month'], $job['e_start_day'], $job['e_start_year']); // OcCLE code require_code('occle'); $temp = new virtual_bash($job_text); $output = $temp->output_html(true); if (is_object($output)) { echo $output->evaluate(); } } } } $job['n_seconds_before'] = 0; } else { // Send notification if (!has_category_access($job['n_member_id'], 'calendar', strval($job['e_type']))) { continue; } $title = get_translated_text($job['e_title']); $timestamp = array_key_exists(0, $recurrences) ? usertime_to_utctime($recurrences[0][0]) : mktime($job['e_start_hour'], $job['e_start_minute'], 0, $job['e_start_month'], $job['e_start_day'], $job['e_start_year']); $date = get_timezoned_date($timestamp, true, false, false, false, $job['n_member_id']); $_url = build_url(array('page' => 'calendar', 'type' => 'view', 'id' => $job['j_event_id']), get_module_zone('calendar'), NULL, false, false, true); $url = $_url->evaluate(); $subject_tag = do_lang('EVENT_REMINDER_SUBJECT', $title, NULL, NULL, get_lang($job['n_member_id'])); $message_raw = do_lang('EVENT_REMINDER_CONTENT', comcode_escape($date), comcode_escape($url), get_translated_text($job['e_content']), get_lang($job['n_member_id'])); dispatch_notification('calendar_reminder', strval($job['e_type']), $subject_tag, $message_raw, array($job['n_member_id']), A_FROM_SYSTEM_UNPRIVILEGED); //echo $subject_tag."\n\n".$message_raw; } // Recreate job for when next reminder due (if appropriate) if (array_key_exists(1, $recurrences)) { $GLOBALS['SITE_DB']->query_insert('calendar_jobs', array('j_time' => usertime_to_utctime($recurrences[1][0]) - $job['n_seconds_before'], 'j_reminder_id' => $job['j_reminder_id'], 'j_member_id' => $job['j_member_id'], 'j_event_id' => $job['j_event_id'])); } } // Delete jobs just run if ($or_list != '') { $GLOBALS['SITE_DB']->query('DELETE FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'calendar_jobs WHERE ' . $or_list); } $start += 300; } while (array_key_exists(0, $jobs)); }