/** * Get the form fields for an event input form. * * @param ?AUTO_LINK The event type (NULL: default) * @param ?integer The year the event starts at (NULL: default) * @param ?integer The month the event starts at (NULL: default) * @param ?integer The day the event starts at (NULL: default) * @param ?integer The hour the event starts at (NULL: default) * @param ?integer The minute the event starts at (NULL: default) * @param SHORT_TEXT The title of the event * @param LONG_TEXT The full text describing the event * @param SHORT_TEXT The recurrence code * @param ?integer The number of recurrences (NULL: none/infinite) * @param BINARY Whether to segregate the comment-topics/rating/trackbacks per-recurrence * @param BINARY Whether it is a public event * @param integer The priority * @range 1 5 * @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) * @param ?integer The minute the event ends at (NULL: not a multi day event) * @param ?ID_TEXT The timezone for the event (NULL: current user's timezone) * @param BINARY Whether the time should be presented in the viewer's own timezone * @param BINARY Whether the event is validated * @param ?BINARY Whether rating is allowed (NULL: decide statistically, based on existing choices) * @param ?SHORT_INTEGER Whether comments are allowed (0=no, 1=yes, 2=review style) (NULL: decide statistically, based on existing choices) * @param ?BINARY Whether trackbacks are allowed (NULL: decide statistically, based on existing choices) * @param LONG_TEXT Notes * @return array A tuple of: (fields, hidden-fields, delete-fields, edit-text, whether all delete fields are specified, posting form text, more fields) */ function get_form_fields($type = NULL, $start_year = NULL, $start_month = NULL, $start_day = NULL, $start_hour = NULL, $start_minute = NULL, $title = '', $content = '', $recurrence = 'none', $recurrences = NULL, $seg_recurrences = 0, $is_public = 1, $priority = 3, $end_year = NULL, $end_month = NULL, $end_day = NULL, $end_hour = NULL, $end_minute = NULL, $timezone = NULL, $do_timezone_conv = 0, $validated = 1, $allow_rating = NULL, $allow_comments = NULL, $allow_trackbacks = NULL, $notes = '') { list($allow_rating, $allow_comments, $allow_trackbacks) = $this->choose_feedback_fields_statistically($allow_rating, $allow_comments, $allow_trackbacks); unset($content); if (is_null($timezone) || $timezone == '') { $timezone = get_users_timezone(); } require_code('form_templates'); if (is_null($type)) { global $NON_CANONICAL_PARAMS; $NON_CANONICAL_PARAMS[] = 'date'; $NON_CANONICAL_PARAMS[] = 'e_type'; $NON_CANONICAL_PARAMS[] = 'validated'; $date = get_param('date', ''); $start_hour = NULL; $start_minute = NULL; if ($date != '') { $date2 = explode(' ', $date); $exploded = explode('-', $date2[0]); //if (count($exploded)!=3) warn_exit(do_lang_tempcode('INTERNAL_ERROR')); $start_year = intval($exploded[0]); $start_month = intval($exploded[1]); $start_day = intval($exploded[2]); if (array_key_exists(1, $date2)) { $exploded = explode(':', $date2[1]); //if (count($exploded)!=2) warn_exit(do_lang_tempcode('INTERNAL_ERROR')); $start_hour = intval($exploded[0]); $start_minute = intval($exploded[1]); } } else { list($start_year, $start_month, $start_day) = array(NULL, NULL, NULL); } $type = get_param_integer('e_type', -1); if ($type == -1) { $type = NULL; } $adding = true; } else { $adding = false; } if (is_null($type)) { $type = db_get_first_id() + 1; } if (is_null($start_month)) { $start_year = intval(date('Y')); $start_month = intval(date('m')); $start_day = intval(date('d')); $start_hour = NULL; $start_minute = NULL; } if ((is_null($end_year) || is_null($end_month) || is_null($end_day)) && $adding) { $end_year = NULL; //$start_year; $end_month = NULL; //$start_month; $end_day = NULL; //$start_day; $end_hour = NULL; $end_minute = NULL; } $fields = new ocp_tempcode(); $hidden = new ocp_tempcode(); $fields->attach(form_input_line(do_lang_tempcode('TITLE'), do_lang_tempcode('DESCRIPTION_TITLE'), 'title', $title, true)); //$fields->attach(form_input_text_comcode(do_lang_tempcode('EVENT_TEXT'),do_lang_tempcode('DESCRIPTION_EVENT_TEXT'),'content',$content,false)); // Type $type_list = nice_get_event_types($type); $fields->attach(form_input_list(do_lang_tempcode('TYPE'), do_lang_tempcode('DESCRIPTION_EVENT_TYPE'), 'type', $type_list)); // Dates $fields->attach(form_input_tick(do_lang_tempcode('ALL_DAY_EVENT'), do_lang_tempcode('DESCRIPTION_ALL_DAY_EVENT'), 'all_day_event', is_null($start_hour))); $fields->attach(form_input_date(do_lang_tempcode('DATE_TIME'), '', 'start', false, false, true, array(is_null($start_minute) ? find_timezone_start_minute_in_utc($timezone, $start_year, $start_month, $start_day) : $start_minute, is_null($start_hour) ? find_timezone_start_hour_in_utc($timezone, $start_year, $start_month, $start_day) : $start_hour, $start_month, $start_day, $start_year), 120, intval(date('Y')) - 100, NULL, NULL, true, $timezone, get_param('date', '') == '')); $fields->attach(form_input_date(do_lang_tempcode('END_DATE_AND_TIME'), do_lang_tempcode('DESCRIPTION_END_DATE_AND_TIME'), 'end', true, is_null($end_year), true, array(is_null($end_minute) ? find_timezone_end_minute_in_utc($timezone, $end_year, $end_month, $end_day) : $end_minute, is_null($end_hour) ? find_timezone_end_hour_in_utc($timezone, $end_year, $end_month, $end_day) : $end_hour, $end_month, $end_day, $end_year), 120, intval(date('Y')) - 100, NULL, NULL, true, $timezone)); if ($validated == 0) { $validated = get_param_integer('validated', 0); } if (has_some_cat_specific_permission(get_member(), 'bypass_validation_' . $this->permissions_require . 'range_content', NULL, $this->permissions_cat_require)) { if (addon_installed('unvalidated')) { $fields->attach(form_input_tick(do_lang_tempcode('VALIDATED'), do_lang_tempcode('DESCRIPTION_VALIDATED'), 'validated', $validated == 1)); } } $fields2 = new ocp_tempcode(); $fields2->attach(do_template('FORM_SCREEN_FIELD_SPACER', array('SECTION_HIDDEN' => true, 'TITLE' => do_lang_tempcode('ADVANCED')))); // More date stuff $list = ''; foreach (get_timezone_list() as $_timezone => $timezone_nice) { $list .= static_evaluate_tempcode(form_input_list_entry($_timezone, $_timezone == $timezone, $timezone_nice)); } $fields2->attach(form_input_list(do_lang_tempcode('EVENT_TIMEZONE'), do_lang_tempcode('DESCRIPTION_EVENT_TIMEZONE'), 'timezone', make_string_tempcode($list))); $fields2->attach(form_input_tick(do_lang_tempcode('DO_TIMEZONE_CONV'), do_lang_tempcode('DESCRIPTION_DO_TIMEZONE_CONV'), 'do_timezone_conv', $do_timezone_conv == 1)); if (has_specific_permission(get_member(), 'add_public_events')) { $fields2->attach(form_input_tick(do_lang_tempcode('IS_PUBLIC'), do_lang_tempcode('DESCRIPTION_IS_PUBLIC'), 'is_public', $is_public == 1)); } // Priority $priority_list = new ocp_tempcode(); $priority_list->attach(form_input_list_entry('1', $priority == 1, do_lang_tempcode('PRIORITY_1'))); $priority_list->attach(form_input_list_entry('2', $priority == 2, do_lang_tempcode('PRIORITY_2'))); $priority_list->attach(form_input_list_entry('3', $priority == 3, do_lang_tempcode('PRIORITY_3'))); $priority_list->attach(form_input_list_entry('4', $priority == 4, do_lang_tempcode('PRIORITY_4'))); $priority_list->attach(form_input_list_entry('5', $priority == 5, do_lang_tempcode('PRIORITY_5'))); $fields2->attach(form_input_list(do_lang_tempcode('PRIORITY'), '', 'priority', $priority_list)); // Recurrence $fields2->attach(do_template('FORM_SCREEN_FIELD_SPACER', array('SECTION_HIDDEN' => true, 'TITLE' => do_lang_tempcode('RECURRENCE')))); if (strpos($recurrence, ' ') === false) { $recurrence_main = $recurrence; $recurrence_pattern = ''; } else { list($recurrence_main, $recurrence_pattern) = explode(' ', $recurrence); } $radios = form_input_radio_entry('recurrence', 'none', true, do_lang_tempcode('NA_EM')); $radios->attach(form_input_radio_entry('recurrence', 'daily', $recurrence_main == 'daily', do_lang_tempcode('DAILY'))); $radios->attach(form_input_radio_entry('recurrence', 'weekly', $recurrence_main == 'weekly', do_lang_tempcode('WEEKLY'))); $radios->attach(form_input_radio_entry('recurrence', 'monthly', $recurrence_main == 'monthly', do_lang_tempcode('MONTHLY'))); $radios->attach(form_input_radio_entry('recurrence', 'yearly', $recurrence_main == 'yearly', do_lang_tempcode('YEARLY'))); $fields2->attach(form_input_radio(do_lang_tempcode('RECURRENCE'), do_lang_tempcode('DESCRIPTION_RECURRENCE'), 'recurrence', $radios)); // xth_dotw_of_monthly $fields2->attach(form_input_line(do_lang_tempcode('RECURRENCE_PATTERN'), do_lang_tempcode('DESCRIPTION_RECURRENCE_PATTERN'), 'recurrence_pattern', $recurrence_pattern, false)); $fields2->attach(form_input_integer(do_lang_tempcode('RECURRENCES'), do_lang_tempcode('DESCRIPTION_RECURRENCES'), 'recurrences', $recurrences, false)); $fields2->attach(form_input_tick(do_lang_tempcode('SEG_RECURRENCES'), do_lang_tempcode('DESCRIPTION_SEG_RECURRENCES'), 'seg_recurrences', $seg_recurrences == 1)); if ($adding && cron_installed()) { $fields2->attach(do_template('FORM_SCREEN_FIELD_SPACER', array('SECTION_HIDDEN' => true, 'TITLE' => do_lang_tempcode('REMINDERS')))); $fields2->attach(form_input_tick(do_lang_tempcode('SIGN_UP_REMINDER'), do_lang_tempcode('DESCRIPTION_SIGN_UP_REMINDER'), 'sign_up_reminder', true)); if (has_specific_permission(get_member(), 'add_public_events')) { $usergroup_list = $GLOBALS['FORUM_DRIVER']->get_usergroup_list(true); if (get_forum_type() == 'ocf') { unset($usergroup_list[db_get_first_id()]); } $t_usergroup_list = new ocp_tempcode(); foreach ($usergroup_list as $id => $name) { $t_usergroup_list->attach(form_input_list_entry(strval($id), false, $name)); } $fields2->attach(form_input_all_and_not(do_lang_tempcode('SIGN_UP_REMINDER_GROUPS'), do_lang_tempcode('DESCRIPTION_SIGN_UP_REMINDER_GROUPS'), 'sign_up_reminder_groups', $t_usergroup_list)); } $fields2->attach(form_input_float(do_lang_tempcode('REMINDER_TIME'), do_lang_tempcode('DESCRIPTION_REMINDER_TIME'), 'hours_before', 1.0, true)); } require_code('feedback2'); $fields2->attach(feedback_fields($allow_rating == 1, $allow_comments == 1, $allow_trackbacks == 1, false, $notes, $allow_comments == 2)); $fields2->attach(get_syndication_option_fields()); return array($fields, $hidden, NULL, NULL, true, NULL, $fields2); }
/** * 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)); }