/** * Detect calendar matches in a time period, in user-time. * * @param MEMBER The member to detect conflicts for * @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) * @param ?array The type filter (NULL: none) * @param boolean Whether to include RSS events in the results * @return array A list of events happening, with time details */ function calendar_matches($member_id, $restrict, $period_start, $period_end, $filter = NULL, $do_rss = true) { 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); } $matches = array(); $where = ''; if ($restrict) { if ($where != '') { $where .= ' AND '; } $where .= '(e_submitter=' . strval((int) $member_id) . ' OR e_is_public=1)'; } if (!is_null($filter)) { foreach ($filter as $a => $b) { if ($b == 0) { if ($where != '') { $where .= ' AND '; } $where .= 'e_type<>' . strval((int) substr($a, 4)); } } } if ($where != '') { $where .= ' AND '; } $where .= '(validated=1 OR e_is_public=0)'; if (addon_installed('syndication_blocks')) { // Determine what feeds to overlay $feed_urls_todo = array(); for ($i = 0; $i < 10; $i++) { $feed_url = post_param('feed_' . strval($i), ocp_admirecookie('feed_' . strval($i), '')); require_code('users_active_actions'); ocp_setcookie('feed_' . strval($i), $feed_url); if ($feed_url != '' && preg_match('#^[\\w\\d\\-\\_]*$#', $feed_url) == 0) { $feed_urls_todo[$feed_url] = NULL; } } $_event_types = list_to_map('id', $GLOBALS['SITE_DB']->query_select('calendar_types', array('id', 't_title', 't_logo', 't_external_feed'))); foreach ($_event_types as $j => $_event_type) { if ($_event_type['t_external_feed'] != '' && (is_null($filter) || !array_key_exists($_event_type['id'], $filter) || $filter[$_event_type['id']] == 1) && has_category_access(get_member(), 'calendar', strval($_event_type['id']))) { $feed_urls_todo[$_event_type['t_external_feed']] = $_event_type['id']; } $_event_types[$j]['text_original'] = get_translated_text($_event_type['t_title']); } $event_types = collapse_2d_complexity('text_original', 't_logo', $_event_types); // Overlay it foreach ($feed_urls_todo as $feed_url => $event_type) { $temp_file_path = ocp_tempnam('feed'); require_code('files'); $write_to_file = fopen($temp_file_path, 'wb'); http_download_file($feed_url, 1024 * 512, false, false, 'ocPortal', NULL, NULL, NULL, NULL, NULL, $write_to_file); if ($GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'] == 'text/calendar' || $GLOBALS['HTTP_DOWNLOAD_MIME_TYPE'] == 'application/octet-stream') { $data = file_get_contents($temp_file_path); require_code('calendar_ical'); $whole = end(explode('BEGIN:VCALENDAR', $data)); $events = explode('BEGIN:VEVENT', $whole); $calendar_nodes = array(); foreach ($events as $key => $items) { $items = preg_replace('#(.+)\\n +(.*)\\n#', '${1}${2}' . "\n", $items); // Merge split lines $nodes = explode("\n", $items); foreach ($nodes as $_child) { if (strpos($_child, ':') === false) { continue; } $child = array('', ''); $in_quotes = false; $j = 0; for ($i = 0; $i < strlen($_child); $i++) { $char = $_child[$i]; if ($char == '"') { $in_quotes = !$in_quotes; } if ($j != 1 && !$in_quotes && $char == ':') { $j++; } else { $child[$j] .= $char; } } $matches2 = array(); if (preg_match('#;TZID=(.*)#', $child[0], $matches2)) { $calendar_nodes[$key]['TZID'] = $matches2[1]; } $child[0] = preg_replace('#;.*#', '', $child[0]); if (array_key_exists("1", $child) && $child[0] !== 'PRODID' && $child[0] !== 'VERSION' && $child[0] !== 'END') { $calendar_nodes[$key][$child[0]] = str_replace(array('\\n', '\\,'), array("\n", ','), trim($child[1])); } } if ($key != 0) { list($full_url, $type_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, $validated, $allow_rating, $allow_comments, $allow_trackbacks, $notes) = get_event_data_ical($calendar_nodes[$key]); $is_public = 1; $event = array('e_recurrence' => $recurrence, 'e_content' => $content, 'e_title' => $title, 'e_id' => $feed_url, 'e_priority' => $priority, 't_logo' => 'calendar/rss', 'e_recurrences' => $recurrences, 'e_seg_recurrences' => $seg_recurrences, 'e_is_public' => $is_public, 'e_start_year' => $start_year, 'e_start_month' => $start_month, 'e_start_day' => $start_day, 'e_start_hour' => $start_hour, 'e_start_minute' => $start_minute, 'e_end_year' => $end_year, 'e_end_month' => $end_month, 'e_end_day' => $end_day, 'e_end_hour' => $end_hour, 'e_end_minute' => $end_minute, 'e_timezone' => $timezone); if (!is_null($event_type)) { $event['t_logo'] = $_event_types[$event_type]['t_logo']; } if (!is_null($type)) { $event['t_title'] = $type; if (array_key_exists($type, $event_types)) { $event['t_logo'] = $event_types[$type]; } } $their_times = find_periods_recurrence($timezone, 0, $start_year, $start_month, $start_day, $start_hour, $start_minute, $end_year, $end_month, $end_day, $end_hour, $end_minute, $recurrence, $recurrences, $period_start, $period_end); // Now search every combination to see if we can get a hit foreach ($their_times as $their) { $matches[] = array($full_url, $event, $their[0], $their[1], $their[2], $their[3], $their[4], $their[5]); } } } } else { require_code('rss'); $rss = new rss($temp_file_path, true); $content = new ocp_tempcode(); foreach ($rss->gleamed_items as $item) { if (array_key_exists('guid', $item)) { $full_url = $item['guid']; } elseif (array_key_exists('comment_url', $item)) { $full_url = $item['comment_url']; } elseif (array_key_exists('full_url', $item)) { $full_url = $item['full_url']; } else { $full_url = ''; } if (array_key_exists('title', $item) && array_key_exists('clean_add_date', $item) && $full_url != '') { $event = array('e_recurrence' => 'none', 'e_content' => array_key_exists('news', $item) ? $item['news'] : '', 'e_title' => $item['title'], 'e_id' => $full_url, 'e_priority' => 'na', 't_logo' => 'calendar/rss', 'e_recurrences' => 1, 'e_seg_recurrences' => '', 'e_is_public' => 1, 'e_timezone' => get_users_timezone()); if (!is_null($event_type)) { $event['t_logo'] = $_event_types[$event_type]['t_logo']; } if (array_key_exists('category', $item)) { $event['t_title'] = $item['category']; if (array_key_exists($item['category'], $event_types)) { $event['t_logo'] = $event_types[$item['category']]; } } $from = utctime_to_usertime($item['clean_add_date']); if ($from >= $period_start && $from < $period_end) { $event += array('e_start_year' => date('Y', $from), 'e_start_month' => date('m', $from), 'e_start_day' => date('D', $from), 'e_start_hour' => date('H', $from), 'e_start_minute' => date('i', $from), 'e_end_year' => NULL, 'e_end_month' => NULL, 'e_end_day' => NULL, 'e_end_hour' => NULL, 'e_end_minute' => NULL); $matches[] = array($full_url, $event, $from, NULL, $from, NULL, $from, NULL); } } } } @unlink($temp_file_path); } } if ($where != '') { $where .= ' AND '; } $where .= '(((e_start_month>=' . strval(intval(date('m', $period_start)) - 1) . ' AND e_start_year=' . date('Y', $period_start) . ' OR e_start_year>' . date('Y', $period_start) . ') AND (e_start_month<=' . strval(intval(date('m', $period_end)) + 1) . ' AND e_start_year=' . date('Y', $period_end) . ' OR e_start_year<' . date('Y', $period_end) . ')) OR ' . db_string_not_equal_to('e_recurrence', 'none') . ')'; $where = ' WHERE ' . $where; $event_count = $GLOBALS['SITE_DB']->query_value_null_ok_full('SELECT COUNT(*) FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'calendar_events e LEFT JOIN ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'calendar_types t ON e.e_type=t.id' . $where); if ($event_count > 2000) { attach_message(do_lang_tempcode('TOO_MANY_TO_CHOOSE_FROM'), 'inform'); return array(); } $events = $GLOBALS['SITE_DB']->query('SELECT *,e.id AS e_id FROM ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'calendar_events e LEFT JOIN ' . $GLOBALS['SITE_DB']->get_table_prefix() . 'calendar_types t ON e.e_type=t.id' . $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'], $event['e_do_timezone_conv'], $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'], $period_start, $period_end); // Now search every combination to see if we can get a hit foreach ($their_times as $their) { $matches[] = array($event['e_id'], $event, $their[0], $their[1], $their[2], $their[3], $their[4], $their[5]); } } global $M_SORT_KEY; $M_SORT_KEY = 2; usort($matches, 'multi_sort'); return $matches; }
/** * Import ical events to members's event calendar. * * @param PATH File path */ function ical_import($file_name) { $data = unixify_line_format(file_get_contents($file_name)); $whole = end(explode('BEGIN:VCALENDAR', $data)); $events = explode('BEGIN:VEVENT', $whole); $calendar_nodes = array(); foreach ($events as $key => $items) { $items = preg_replace('#(.+)\\n +(.*)\\n#', '${1}${2}' . "\n", $items); // Merge split lines $nodes = explode("\n", $items); foreach ($nodes as $_child) { if (strpos($_child, ':') === false) { continue; } $child = array('', ''); $in_quotes = false; $j = 0; for ($i = 0; $i < strlen($_child); $i++) { $char = $_child[$i]; if ($char == '"') { $in_quotes = !$in_quotes; } if ($j != 1 && !$in_quotes && $char == ':') { $j++; } else { $child[$j] .= $char; } } $matches = array(); if (preg_match('#;TZID=(.*)#', $child[0], $matches)) { $calendar_nodes[$key]['TZID'] = $matches[1]; } $child[0] = preg_replace('#;.*#', '', $child[0]); if (array_key_exists(1, $child) && $child[0] !== 'PRODID' && $child[0] !== 'VERSION' && $child[0] !== 'END') { $calendar_nodes[$key][$child[0]] = trim($child[1]); } } if ($key != 0) { list(, $type_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, $validated, $allow_rating, $allow_comments, $allow_trackbacks, $notes) = get_event_data_ical($calendar_nodes[$key]); if (is_null($type_id)) { require_code('calendar2'); $type_id = add_event_type(ucfirst($type), 'calendar/general'); } $id = add_calendar_event($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, 1, $validated, $allow_rating, $allow_comments, $allow_trackbacks, $notes); } } }