Yoshi2889 /
SMF2.1
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * This file has only one real task, showing the calendar. |
||
| 5 | * Original module by Aaron O'Neil - [email protected] |
||
| 6 | * |
||
| 7 | * Simple Machines Forum (SMF) |
||
| 8 | * |
||
| 9 | * @package SMF |
||
| 10 | * @author Simple Machines http://www.simplemachines.org |
||
| 11 | * @copyright 2017 Simple Machines and individual contributors |
||
| 12 | * @license http://www.simplemachines.org/about/smf/license.php BSD |
||
| 13 | * |
||
| 14 | * @version 2.1 Beta 4 |
||
| 15 | */ |
||
| 16 | |||
| 17 | if (!defined('SMF')) |
||
| 18 | die('No direct access...'); |
||
| 19 | |||
| 20 | /** |
||
| 21 | * Show the calendar. |
||
| 22 | * It loads the specified month's events, holidays, and birthdays. |
||
| 23 | * It requires the calendar_view permission. |
||
| 24 | * It depends on the cal_enabled setting, and many of the other cal_ settings. |
||
| 25 | * It uses the calendar_start_day theme option. (Monday/Sunday) |
||
| 26 | * It uses the main sub template in the Calendar template. |
||
| 27 | * It goes to the month and year passed in 'month' and 'year' by get or post. |
||
| 28 | * It is accessed through ?action=calendar. |
||
| 29 | * @return void |
||
| 30 | */ |
||
| 31 | function CalendarMain() |
||
| 32 | { |
||
| 33 | global $txt, $context, $modSettings, $scripturl, $options, $sourcedir, $user_info, $smcFunc; |
||
| 34 | |||
| 35 | // Permissions, permissions, permissions. |
||
| 36 | isAllowedTo('calendar_view'); |
||
| 37 | |||
| 38 | // Some global template resources. |
||
| 39 | $context['calendar_resources'] = array( |
||
| 40 | 'min_year' => $modSettings['cal_minyear'], |
||
| 41 | 'max_year' => $modSettings['cal_maxyear'], |
||
| 42 | ); |
||
| 43 | |||
| 44 | // Doing something other than calendar viewing? |
||
| 45 | $subActions = array( |
||
| 46 | 'ical' => 'iCalDownload', |
||
| 47 | 'post' => 'CalendarPost', |
||
| 48 | ); |
||
| 49 | |||
| 50 | if (isset($_GET['sa']) && isset($subActions[$_GET['sa']])) |
||
| 51 | return call_helper($subActions[$_GET['sa']]); |
||
| 52 | |||
| 53 | // You can't do anything if the calendar is off. |
||
| 54 | if (empty($modSettings['cal_enabled'])) |
||
| 55 | fatal_lang_error('calendar_off', false); |
||
| 56 | |||
| 57 | // This is gonna be needed... |
||
| 58 | loadTemplate('Calendar'); |
||
| 59 | loadCSSFile('calendar.css', array('force_current' => false, 'validate' => true, 'rtl' => 'calendar.rtl.css'), 'smf_calendar'); |
||
| 60 | |||
| 61 | // Did the specify an individual event ID? If so, let's splice the year/month in to what we would otherwise be doing. |
||
| 62 | if (isset($_GET['event'])) |
||
| 63 | { |
||
| 64 | $evid = (int) $_GET['event']; |
||
| 65 | View Code Duplication | if ($evid > 0) |
|
| 66 | { |
||
| 67 | $request = $smcFunc['db_query']('', ' |
||
| 68 | SELECT start_date |
||
| 69 | FROM {db_prefix}calendar |
||
| 70 | WHERE id_event = {int:event_id}', |
||
| 71 | array( |
||
| 72 | 'event_id' => $evid, |
||
| 73 | ) |
||
| 74 | ); |
||
| 75 | if ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 76 | { |
||
| 77 | $_REQUEST['start_date'] = $row['start_date']; |
||
| 78 | |||
| 79 | // We might use this later. |
||
| 80 | $context['selected_event'] = $evid; |
||
| 81 | } |
||
| 82 | $smcFunc['db_free_result']($request); |
||
| 83 | } |
||
| 84 | unset ($_GET['event']); |
||
| 85 | } |
||
| 86 | |||
| 87 | // Set the page title to mention the calendar ;). |
||
| 88 | $context['page_title'] = $txt['calendar']; |
||
| 89 | |||
| 90 | // Ensure a default view is defined |
||
| 91 | if (empty($modSettings['calendar_default_view'])) |
||
| 92 | $modSettings['calendar_default_view'] = 'viewlist'; |
||
| 93 | |||
| 94 | // What view do we want? |
||
| 95 | if (isset($_GET['viewweek'])) |
||
| 96 | $context['calendar_view'] = 'viewweek'; |
||
| 97 | elseif (isset($_GET['viewmonth'])) |
||
| 98 | $context['calendar_view'] = 'viewmonth'; |
||
| 99 | elseif (isset($_GET['viewlist'])) |
||
| 100 | $context['calendar_view'] = 'viewlist'; |
||
| 101 | else |
||
| 102 | $context['calendar_view'] = $modSettings['calendar_default_view']; |
||
| 103 | |||
| 104 | // Don't let search engines index the non-default calendar pages |
||
| 105 | if ($context['calendar_view'] !== $modSettings['calendar_default_view']) |
||
| 106 | $context['robot_no_index'] = true; |
||
| 107 | |||
| 108 | // Get the current day of month... |
||
| 109 | require_once($sourcedir . '/Subs-Calendar.php'); |
||
| 110 | $today = getTodayInfo(); |
||
| 111 | |||
| 112 | // Need a start date for all views |
||
| 113 | View Code Duplication | if (!empty($_REQUEST['start_date'])) |
|
| 114 | { |
||
| 115 | $start_parsed = date_parse($_REQUEST['start_date']); |
||
| 116 | if (empty($start_parsed['error_count']) && empty($start_parsed['warning_count'])) |
||
| 117 | { |
||
| 118 | $_REQUEST['year'] = $start_parsed['year']; |
||
| 119 | $_REQUEST['month'] = $start_parsed['month']; |
||
| 120 | $_REQUEST['day'] = $start_parsed['day']; |
||
| 121 | } |
||
| 122 | } |
||
| 123 | $year = !empty($_REQUEST['year']) ? (int) $_REQUEST['year'] : $today['year']; |
||
| 124 | $month = !empty($_REQUEST['month']) ? (int) $_REQUEST['month'] : $today['month']; |
||
| 125 | $day = !empty($_REQUEST['day']) ? (int) $_REQUEST['day'] : (!empty($_REQUEST['month']) ? 1 : $today['day']); |
||
| 126 | |||
| 127 | $start_object = checkdate($month, $day, $year) === true ? date_create(implode('-', array($year, $month, $day))) : date_create(implode('-', array($today['year'], $today['month'], $today['day']))); |
||
| 128 | |||
| 129 | // Need an end date for the list view |
||
| 130 | View Code Duplication | if (!empty($_REQUEST['end_date'])) |
|
| 131 | { |
||
| 132 | $end_parsed = date_parse($_REQUEST['end_date']); |
||
| 133 | if (empty($end_parsed['error_count']) && empty($end_parsed['warning_count'])) |
||
| 134 | { |
||
| 135 | $_REQUEST['end_year'] = $end_parsed['year']; |
||
| 136 | $_REQUEST['end_month'] = $end_parsed['month']; |
||
| 137 | $_REQUEST['end_day'] = $end_parsed['day']; |
||
| 138 | } |
||
| 139 | } |
||
| 140 | $end_year = !empty($_REQUEST['end_year']) ? (int) $_REQUEST['end_year'] : null; |
||
| 141 | $end_month = !empty($_REQUEST['end_month']) ? (int) $_REQUEST['end_month'] : null; |
||
| 142 | $end_day = !empty($_REQUEST['end_day']) ? (int) $_REQUEST['end_day'] : null; |
||
| 143 | |||
| 144 | $end_object = checkdate($end_month, $end_day, $end_year) === true ? date_create(implode('-', array($end_year, $end_month, $end_day))) : null; |
||
| 145 | |||
| 146 | if (empty($end_object) || $start_object >= $end_object) |
||
| 147 | { |
||
| 148 | $num_days_shown = empty($modSettings['cal_days_for_index']) || $modSettings['cal_days_for_index'] < 1 ? 1 : $modSettings['cal_days_for_index']; |
||
| 149 | |||
| 150 | $end_object = date_create(date_format($start_object, 'Y-m-d')); |
||
| 151 | |||
| 152 | date_add($end_object, date_interval_create_from_date_string($num_days_shown . ' days')); |
||
| 153 | } |
||
| 154 | |||
| 155 | $curPage = array( |
||
| 156 | 'year' => date_format($start_object, 'Y'), |
||
| 157 | 'month' => date_format($start_object, 'n'), |
||
| 158 | 'day' => date_format($start_object, 'j'), |
||
| 159 | 'start_date' => date_format($start_object, 'Y-m-d'), |
||
| 160 | 'end_year' => date_format($end_object, 'Y'), |
||
| 161 | 'end_month' => date_format($end_object, 'n'), |
||
| 162 | 'end_day' => date_format($end_object, 'j'), |
||
| 163 | 'end_date' => date_format($end_object, 'Y-m-d'), |
||
| 164 | ); |
||
| 165 | |||
| 166 | // Make sure the year and month are in valid ranges. |
||
| 167 | if ($curPage['month'] < 1 || $curPage['month'] > 12) |
||
| 168 | fatal_lang_error('invalid_month', false); |
||
| 169 | View Code Duplication | if ($curPage['year'] < $modSettings['cal_minyear'] || $curPage['year'] > $modSettings['cal_maxyear']) |
|
| 170 | fatal_lang_error('invalid_year', false); |
||
| 171 | // If we have a day clean that too. |
||
| 172 | if ($context['calendar_view'] != 'viewmonth') |
||
| 173 | { |
||
| 174 | $isValid = checkdate($curPage['month'], $curPage['day'], $curPage['year']); |
||
| 175 | if (!$isValid) |
||
| 176 | fatal_lang_error('invalid_day', false); |
||
| 177 | } |
||
| 178 | |||
| 179 | // Load all the context information needed to show the calendar grid. |
||
| 180 | $calendarOptions = array( |
||
| 181 | 'start_day' => !empty($options['calendar_start_day']) ? $options['calendar_start_day'] : 0, |
||
| 182 | 'show_birthdays' => in_array($modSettings['cal_showbdays'], array(1, 2)), |
||
| 183 | 'show_events' => in_array($modSettings['cal_showevents'], array(1, 2)), |
||
| 184 | 'show_holidays' => in_array($modSettings['cal_showholidays'], array(1, 2)), |
||
| 185 | 'highlight' => array( |
||
| 186 | 'events' => isset($modSettings['cal_highlight_events']) ? $modSettings['cal_highlight_events'] : 0, |
||
| 187 | 'holidays' => isset($modSettings['cal_highlight_holidays']) ? $modSettings['cal_highlight_holidays'] : 0, |
||
| 188 | 'birthdays' => isset($modSettings['cal_highlight_birthdays']) ? $modSettings['cal_highlight_birthdays'] : 0, |
||
| 189 | ), |
||
| 190 | 'show_week_num' => true, |
||
| 191 | 'short_day_titles' => !empty($modSettings['cal_short_days']), |
||
| 192 | 'short_month_titles' => !empty($modSettings['cal_short_months']), |
||
| 193 | 'show_next_prev' => !empty($modSettings['cal_prev_next_links']), |
||
| 194 | 'show_week_links' => isset($modSettings['cal_week_links']) ? $modSettings['cal_week_links'] : 0, |
||
| 195 | ); |
||
| 196 | |||
| 197 | // Load up the main view. |
||
| 198 | if ($context['calendar_view'] == 'viewlist') |
||
| 199 | $context['calendar_grid_main'] = getCalendarList($curPage['start_date'], $curPage['end_date'], $calendarOptions); |
||
| 200 | elseif ($context['calendar_view'] == 'viewweek') |
||
| 201 | $context['calendar_grid_main'] = getCalendarWeek($curPage['month'], $curPage['year'], $curPage['day'], $calendarOptions); |
||
| 202 | else |
||
| 203 | $context['calendar_grid_main'] = getCalendarGrid($curPage['month'], $curPage['year'], $calendarOptions); |
||
| 204 | |||
| 205 | // Load up the previous and next months. |
||
| 206 | $context['calendar_grid_current'] = getCalendarGrid($curPage['month'], $curPage['year'], $calendarOptions); |
||
| 207 | |||
| 208 | // Only show previous month if it isn't pre-January of the min-year |
||
| 209 | View Code Duplication | if ($context['calendar_grid_current']['previous_calendar']['year'] > $modSettings['cal_minyear'] || $curPage['month'] != 1) |
|
| 210 | $context['calendar_grid_prev'] = getCalendarGrid($context['calendar_grid_current']['previous_calendar']['month'], $context['calendar_grid_current']['previous_calendar']['year'], $calendarOptions, true); |
||
| 211 | |||
| 212 | // Only show next month if it isn't post-December of the max-year |
||
| 213 | View Code Duplication | if ($context['calendar_grid_current']['next_calendar']['year'] < $modSettings['cal_maxyear'] || $curPage['month'] != 12) |
|
| 214 | $context['calendar_grid_next'] = getCalendarGrid($context['calendar_grid_current']['next_calendar']['month'], $context['calendar_grid_current']['next_calendar']['year'], $calendarOptions); |
||
| 215 | |||
| 216 | // Basic template stuff. |
||
| 217 | $context['allow_calendar_event'] = allowedTo('calendar_post'); |
||
| 218 | |||
| 219 | // If you don't allow events not linked to posts and you're not an admin, we have more work to do... |
||
| 220 | View Code Duplication | if ($context['allow_calendar_event'] && empty($modSettings['cal_allow_unlinked']) && !$user_info['is_admin']) |
|
| 221 | { |
||
| 222 | $boards_can_post = boardsAllowedTo('post_new'); |
||
| 223 | $context['allow_calendar_event'] &= !empty($boards_can_post); |
||
| 224 | } |
||
| 225 | |||
| 226 | $context['can_post'] = $context['allow_calendar_event']; |
||
| 227 | $context['current_day'] = $curPage['day']; |
||
| 228 | $context['current_month'] = $curPage['month']; |
||
| 229 | $context['current_year'] = $curPage['year']; |
||
| 230 | $context['show_all_birthdays'] = isset($_GET['showbd']); |
||
| 231 | $context['blocks_disabled'] = !empty($modSettings['cal_disable_prev_next']) ? 1 : 0; |
||
| 232 | |||
| 233 | // Set the page title to mention the month or week, too |
||
| 234 | if ($context['calendar_view'] != 'viewlist') |
||
| 235 | $context['page_title'] .= ' - ' . ($context['calendar_view'] == 'viewweek' ? $context['calendar_grid_main']['week_title'] : $txt['months'][$context['current_month']] . ' ' . $context['current_year']); |
||
| 236 | |||
| 237 | // Load up the linktree! |
||
| 238 | $context['linktree'][] = array( |
||
| 239 | 'url' => $scripturl . '?action=calendar', |
||
| 240 | 'name' => $txt['calendar'] |
||
| 241 | ); |
||
| 242 | // Add the current month to the linktree. |
||
| 243 | $context['linktree'][] = array( |
||
| 244 | 'url' => $scripturl . '?action=calendar;year=' . $context['current_year'] . ';month=' . $context['current_month'], |
||
| 245 | 'name' => $txt['months'][$context['current_month']] . ' ' . $context['current_year'] |
||
| 246 | ); |
||
| 247 | // If applicable, add the current week to the linktree. |
||
| 248 | if ($context['calendar_view'] == 'viewweek') |
||
| 249 | $context['linktree'][] = array( |
||
| 250 | 'url' => $scripturl . '?action=calendar;viewweek;year=' . $context['current_year'] . ';month=' . $context['current_month'] . ';day=' . $context['current_day'], |
||
| 251 | 'name' => $context['calendar_grid_main']['week_title'], |
||
| 252 | ); |
||
| 253 | |||
| 254 | // Build the calendar button array. |
||
| 255 | $context['calendar_buttons'] = array(); |
||
| 256 | |||
| 257 | if ($context['can_post']) |
||
| 258 | $context['calendar_buttons']['post_event'] = array('text' => 'calendar_post_event', 'image' => 'calendarpe.png', 'url' => $scripturl . '?action=calendar;sa=post;month=' . $context['current_month'] . ';year=' . $context['current_year'] . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 259 | |||
| 260 | // Allow mods to add additional buttons here |
||
| 261 | call_integration_hook('integrate_calendar_buttons'); |
||
| 262 | } |
||
| 263 | |||
| 264 | /** |
||
| 265 | * This function processes posting/editing/deleting a calendar event. |
||
| 266 | * |
||
| 267 | * - calls {@link Post.php|Post() Post()} function if event is linked to a post. |
||
| 268 | * - calls {@link Subs-Calendar.php|insertEvent() insertEvent()} to insert the event if not linked to post. |
||
| 269 | * |
||
| 270 | * It requires the calendar_post permission to use. |
||
| 271 | * It uses the event_post sub template in the Calendar template. |
||
| 272 | * It is accessed with ?action=calendar;sa=post. |
||
| 273 | */ |
||
| 274 | function CalendarPost() |
||
| 275 | { |
||
| 276 | global $context, $txt, $user_info, $sourcedir, $scripturl; |
||
| 277 | global $modSettings, $topic, $smcFunc; |
||
| 278 | |||
| 279 | // Well - can they? |
||
| 280 | isAllowedTo('calendar_post'); |
||
| 281 | |||
| 282 | // We need these for all kinds of useful functions. |
||
| 283 | require_once($sourcedir . '/Subs-Calendar.php'); |
||
| 284 | require_once($sourcedir . '/Subs.php'); |
||
| 285 | |||
| 286 | // Cast this for safety... |
||
| 287 | if (isset($_REQUEST['eventid'])) |
||
| 288 | $_REQUEST['eventid'] = (int) $_REQUEST['eventid']; |
||
| 289 | |||
| 290 | // We want a fairly compact version of the time, but as close as possible to the user's settings. |
||
| 291 | View Code Duplication | if (preg_match('~%[HkIlMpPrRSTX](?:[^%]*%[HkIlMpPrRSTX])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) |
|
| 292 | $time_string = '%k:%M'; |
||
| 293 | else |
||
| 294 | $time_string = str_replace(array('%I', '%H', '%S', '%r', '%R', '%T'), array('%l', '%k', '', '%l:%M %p', '%k:%M', '%l:%M'), $matches[0]); |
||
| 295 | |||
| 296 | $js_time_string = str_replace( |
||
| 297 | array('%H', '%k', '%I', '%l', '%M', '%p', '%P', '%r', '%R', '%S', '%T', '%X'), |
||
| 298 | array('H', 'G', 'h', 'g', 'i', 'A', 'a', 'h:i:s A', 'H:i', 's', 'H:i:s', 'H:i:s'), |
||
| 299 | $time_string |
||
| 300 | ); |
||
| 301 | |||
| 302 | // Submitting? |
||
| 303 | if (isset($_POST[$context['session_var']], $_REQUEST['eventid'])) |
||
| 304 | { |
||
| 305 | checkSession(); |
||
| 306 | |||
| 307 | // Validate the post... |
||
| 308 | if (!isset($_POST['link_to_board'])) |
||
| 309 | validateEventPost(); |
||
| 310 | |||
| 311 | // If you're not allowed to edit any events, you have to be the poster. |
||
| 312 | if ($_REQUEST['eventid'] > 0 && !allowedTo('calendar_edit_any')) |
||
| 313 | isAllowedTo('calendar_edit_' . (!empty($user_info['id']) && getEventPoster($_REQUEST['eventid']) == $user_info['id'] ? 'own' : 'any')); |
||
| 314 | |||
| 315 | // New - and directing? |
||
| 316 | if (isset($_POST['link_to_board']) || empty($modSettings['cal_allow_unlinked'])) |
||
| 317 | { |
||
| 318 | $_REQUEST['calendar'] = 1; |
||
| 319 | require_once($sourcedir . '/Post.php'); |
||
| 320 | return Post(); |
||
| 321 | } |
||
| 322 | // New... |
||
| 323 | elseif ($_REQUEST['eventid'] == -1) |
||
| 324 | { |
||
| 325 | $eventOptions = array( |
||
| 326 | 'board' => 0, |
||
| 327 | 'topic' => 0, |
||
| 328 | 'title' => $smcFunc['substr']($_REQUEST['evtitle'], 0, 100), |
||
| 329 | 'location' => $smcFunc['substr']($_REQUEST['event_location'], 0, 255), |
||
| 330 | 'member' => $user_info['id'], |
||
| 331 | ); |
||
| 332 | insertEvent($eventOptions); |
||
| 333 | } |
||
| 334 | |||
| 335 | // Deleting... |
||
| 336 | elseif (isset($_REQUEST['deleteevent'])) |
||
| 337 | removeEvent($_REQUEST['eventid']); |
||
| 338 | |||
| 339 | // ... or just update it? |
||
| 340 | else |
||
| 341 | { |
||
| 342 | $eventOptions = array( |
||
| 343 | 'title' => $smcFunc['substr']($_REQUEST['evtitle'], 0, 100), |
||
| 344 | 'location' => $smcFunc['substr']($_REQUEST['event_location'], 0, 255), |
||
| 345 | ); |
||
| 346 | modifyEvent($_REQUEST['eventid'], $eventOptions); |
||
| 347 | } |
||
| 348 | |||
| 349 | updateSettings(array( |
||
| 350 | 'calendar_updated' => time(), |
||
| 351 | )); |
||
| 352 | |||
| 353 | // No point hanging around here now... |
||
| 354 | if (isset($_POST['start_date'])) |
||
| 355 | { |
||
| 356 | $d = date_parse($_POST['start_date']); |
||
| 357 | $year = $d['year']; |
||
| 358 | $month = $d['month']; |
||
| 359 | $day = $d['day']; |
||
| 360 | } |
||
| 361 | elseif (isset($_POST['start_datetime'])) |
||
| 362 | { |
||
| 363 | $d = date_parse($_POST['start_datetime']); |
||
| 364 | $year = $d['year']; |
||
| 365 | $month = $d['month']; |
||
| 366 | $day = $d['day']; |
||
| 367 | } |
||
| 368 | else |
||
| 369 | { |
||
| 370 | $today = getdate(); |
||
| 371 | $year = isset($_POST['year']) ? $_POST['year'] : $today['year']; |
||
| 372 | $month = isset($_POST['month']) ? $_POST['month'] : $today['mon']; |
||
| 373 | $day = isset($_POST['day']) ? $_POST['day'] : $today['mday']; |
||
| 374 | } |
||
| 375 | redirectexit($scripturl . '?action=calendar;month=' . $month . ';year=' . $year . ';day=' . $day); |
||
| 376 | } |
||
| 377 | |||
| 378 | // If we are not enabled... we are not enabled. |
||
| 379 | if (empty($modSettings['cal_allow_unlinked']) && empty($_REQUEST['eventid'])) |
||
| 380 | { |
||
| 381 | $_REQUEST['calendar'] = 1; |
||
| 382 | require_once($sourcedir . '/Post.php'); |
||
| 383 | return Post(); |
||
| 384 | } |
||
| 385 | |||
| 386 | // New? |
||
| 387 | if (!isset($_REQUEST['eventid'])) |
||
| 388 | { |
||
| 389 | $context['event'] = array( |
||
| 390 | 'boards' => array(), |
||
| 391 | 'board' => 0, |
||
| 392 | 'new' => 1, |
||
| 393 | 'eventid' => -1, |
||
| 394 | 'title' => '', |
||
| 395 | 'location' => '', |
||
| 396 | ); |
||
| 397 | |||
| 398 | $eventDatetimes = getNewEventDatetimes(); |
||
| 399 | $context['event'] = array_merge($context['event'], $eventDatetimes); |
||
| 400 | |||
| 401 | $context['event']['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $context['event']['month'] == 12 ? 1 : $context['event']['month'] + 1, 0, $context['event']['month'] == 12 ? $context['event']['year'] + 1 : $context['event']['year'])); |
||
| 402 | } |
||
| 403 | else |
||
| 404 | { |
||
| 405 | $context['event'] = getEventProperties($_REQUEST['eventid']); |
||
| 406 | |||
| 407 | if ($context['event'] === false) |
||
| 408 | fatal_lang_error('no_access', false); |
||
| 409 | |||
| 410 | // If it has a board, then they should be editing it within the topic. |
||
| 411 | if (!empty($context['event']['topic']['id']) && !empty($context['event']['topic']['first_msg'])) |
||
| 412 | { |
||
| 413 | // We load the board up, for a check on the board access rights... |
||
| 414 | $topic = $context['event']['topic']['id']; |
||
| 415 | loadBoard(); |
||
| 416 | } |
||
| 417 | |||
| 418 | // Make sure the user is allowed to edit this event. |
||
| 419 | if ($context['event']['member'] != $user_info['id']) |
||
| 420 | isAllowedTo('calendar_edit_any'); |
||
| 421 | elseif (!allowedTo('calendar_edit_any')) |
||
| 422 | isAllowedTo('calendar_edit_own'); |
||
| 423 | } |
||
| 424 | |||
| 425 | // An all day event? Set up some nice defaults in case the user wants to change that |
||
| 426 | View Code Duplication | if ($context['event']['allday'] == true) |
|
| 427 | { |
||
| 428 | $context['event']['tz'] = getUserTimezone(); |
||
| 429 | $context['event']['start_time'] = timeformat(time(), $time_string); |
||
| 430 | $context['event']['end_time'] = timeformat(time() + 3600, $time_string); |
||
| 431 | } |
||
| 432 | // Otherwise, just adjust these to look nice on the input form |
||
| 433 | else |
||
| 434 | { |
||
| 435 | $context['event']['start_time'] = $context['event']['start_time_orig']; |
||
| 436 | $context['event']['end_time'] = $context['event']['end_time_orig']; |
||
| 437 | } |
||
| 438 | |||
| 439 | // Need this so the user can select a timezone for the event. |
||
| 440 | $context['all_timezones'] = smf_list_timezones($context['event']['start_date']); |
||
| 441 | unset($context['all_timezones']['']); |
||
| 442 | |||
| 443 | // If the event's timezone is not in SMF's standard list of time zones, prepend it to the list |
||
| 444 | View Code Duplication | if (!in_array($context['event']['tz'], array_keys($context['all_timezones']))) |
|
| 445 | { |
||
| 446 | $d = date_create($context['event']['start_datetime'] . ' ' . $context['event']['tz']); |
||
| 447 | $context['all_timezones'] = array($context['event']['tz'] => fix_tz_abbrev($context['event']['tz'], date_format($d, 'T')) . ' - ' . $context['event']['tz'] . ' [UTC' . date_format($d, 'P') . ']') + $context['all_timezones']; |
||
| 448 | } |
||
| 449 | |||
| 450 | // Get list of boards that can be posted in. |
||
| 451 | $boards = boardsAllowedTo('post_new'); |
||
| 452 | if (empty($boards)) |
||
| 453 | { |
||
| 454 | // You can post new events but can't link them to anything... |
||
| 455 | $context['event']['categories'] = array(); |
||
| 456 | } |
||
| 457 | else |
||
| 458 | { |
||
| 459 | // Load the list of boards and categories in the context. |
||
| 460 | require_once($sourcedir . '/Subs-MessageIndex.php'); |
||
| 461 | $boardListOptions = array( |
||
| 462 | 'included_boards' => in_array(0, $boards) ? null : $boards, |
||
| 463 | 'not_redirection' => true, |
||
| 464 | 'use_permissions' => true, |
||
| 465 | 'selected_board' => $modSettings['cal_defaultboard'], |
||
| 466 | ); |
||
| 467 | $context['event']['categories'] = getBoardList($boardListOptions); |
||
| 468 | } |
||
| 469 | |||
| 470 | // Template, sub template, etc. |
||
| 471 | loadTemplate('Calendar'); |
||
| 472 | $context['sub_template'] = 'event_post'; |
||
| 473 | |||
| 474 | $context['page_title'] = isset($_REQUEST['eventid']) ? $txt['calendar_edit'] : $txt['calendar_post_event']; |
||
| 475 | $context['linktree'][] = array( |
||
| 476 | 'name' => $context['page_title'], |
||
| 477 | ); |
||
| 478 | |||
| 479 | loadCSSFile('jquery-ui.datepicker.css', array('defer' => false), 'smf_datepicker'); |
||
| 480 | loadCSSFile('jquery.timepicker.css', array('defer' => false), 'smf_timepicker'); |
||
| 481 | loadJavaScriptFile('jquery-ui.datepicker.min.js', array('defer' => true), 'smf_datepicker'); |
||
| 482 | loadJavaScriptFile('jquery.timepicker.min.js', array('defer' => true), 'smf_timepicker'); |
||
| 483 | loadJavaScriptFile('datepair.min.js', array('defer' => true), 'smf_datepair'); |
||
| 484 | addInlineJavaScript(' |
||
| 485 | $("#allday").click(function(){ |
||
| 486 | $("#start_time").attr("disabled", this.checked); |
||
| 487 | $("#end_time").attr("disabled", this.checked); |
||
| 488 | $("#tz").attr("disabled", this.checked); |
||
| 489 | }); |
||
| 490 | $("#event_time_input .date_input").datepicker({ |
||
| 491 | dateFormat: "yy-mm-dd", |
||
| 492 | autoSize: true, |
||
| 493 | isRTL: ' . ($context['right_to_left'] ? 'true' : 'false') . ', |
||
| 494 | constrainInput: true, |
||
| 495 | showAnim: "", |
||
| 496 | showButtonPanel: false, |
||
| 497 | minDate: "' . $modSettings['cal_minyear'] . '-01-01", |
||
| 498 | maxDate: "' . $modSettings['cal_maxyear'] . '-12-31", |
||
| 499 | yearRange: "' . $modSettings['cal_minyear'] . ':' . $modSettings['cal_maxyear'] . '", |
||
| 500 | hideIfNoPrevNext: true, |
||
| 501 | monthNames: ["' . implode('", "', $txt['months_titles']) . '"], |
||
| 502 | monthNamesShort: ["' . implode('", "', $txt['months_short']) . '"], |
||
| 503 | dayNames: ["' . implode('", "', $txt['days']) . '"], |
||
| 504 | dayNamesShort: ["' . implode('", "', $txt['days_short']) . '"], |
||
| 505 | dayNamesMin: ["' . implode('", "', $txt['days_short']) . '"], |
||
| 506 | prevText: "' . $txt['prev_month'] . '", |
||
| 507 | nextText: "' . $txt['next_month'] . '", |
||
| 508 | }); |
||
| 509 | $(".time_input").timepicker({ |
||
| 510 | timeFormat: "' . $js_time_string . '", |
||
| 511 | showDuration: true, |
||
| 512 | maxTime: "23:59:59", |
||
| 513 | }); |
||
| 514 | var date_entry = document.getElementById("event_time_input"); |
||
| 515 | var date_entry_pair = new Datepair(date_entry, { |
||
| 516 | timeClass: "time_input", |
||
| 517 | dateClass: "date_input", |
||
| 518 | parseDate: function (el) { |
||
| 519 | var utc = new Date($(el).datepicker("getDate")); |
||
| 520 | return utc && new Date(utc.getTime() + (utc.getTimezoneOffset() * 60000)); |
||
| 521 | }, |
||
| 522 | updateDate: function (el, v) { |
||
| 523 | $(el).datepicker("setDate", new Date(v.getTime() - (v.getTimezoneOffset() * 60000))); |
||
| 524 | } |
||
| 525 | }); |
||
| 526 | ', true); |
||
| 527 | } |
||
| 528 | |||
| 529 | /** |
||
| 530 | * This function offers up a download of an event in iCal 2.0 format. |
||
| 531 | * |
||
| 532 | * Follows the conventions in {@link https://tools.ietf.org/html/rfc5546 RFC5546} |
||
| 533 | * Sets events as all day events since we don't have hourly events |
||
| 534 | * Will honor and set multi day events |
||
| 535 | * Sets a sequence number if the event has been modified |
||
| 536 | * |
||
| 537 | * @todo .... allow for week or month export files as well? |
||
| 538 | */ |
||
| 539 | function iCalDownload() |
||
| 540 | { |
||
| 541 | global $smcFunc, $sourcedir, $forum_version, $modSettings, $webmaster_email, $mbname; |
||
| 542 | |||
| 543 | // You can't export if the calendar export feature is off. |
||
| 544 | if (empty($modSettings['cal_export'])) |
||
| 545 | fatal_lang_error('calendar_export_off', false); |
||
| 546 | |||
| 547 | // Goes without saying that this is required. |
||
| 548 | if (!isset($_REQUEST['eventid'])) |
||
| 549 | fatal_lang_error('no_access', false); |
||
| 550 | |||
| 551 | // This is kinda wanted. |
||
| 552 | require_once($sourcedir . '/Subs-Calendar.php'); |
||
| 553 | |||
| 554 | // Load up the event in question and check it exists. |
||
| 555 | $event = getEventProperties($_REQUEST['eventid']); |
||
| 556 | |||
| 557 | if ($event === false) |
||
| 558 | fatal_lang_error('no_access', false); |
||
| 559 | |||
| 560 | // Check the title isn't too long - iCal requires some formatting if so. |
||
| 561 | $title = str_split($event['title'], 30); |
||
| 562 | foreach ($title as $id => $line) |
||
| 563 | { |
||
| 564 | if ($id != 0) |
||
| 565 | $title[$id] = ' ' . $title[$id]; |
||
| 566 | $title[$id] .= "\n"; |
||
| 567 | } |
||
| 568 | |||
| 569 | // Format the dates. |
||
| 570 | $datestamp = date('Ymd\THis\Z', time()); |
||
| 571 | $start_date = date_create($event['start_date'] . (isset($event['start_time']) ? ' ' . $event['start_time'] : '') . (isset($event['tz']) ? ' ' . $event['tz'] : '')); |
||
| 572 | $end_date = date_create($event['end_date'] . (isset($event['end_time']) ? ' ' . $event['end_time'] : '') . (isset($event['tz']) ? ' ' . $event['tz'] : '')); |
||
| 573 | |||
| 574 | if (!empty($event['start_time'])) |
||
| 575 | { |
||
| 576 | $datestart = date_format($start_date, 'Ymd\THis'); |
||
| 577 | $dateend = date_format($end_date, 'Ymd\THis'); |
||
| 578 | } |
||
| 579 | else |
||
| 580 | { |
||
| 581 | $datestart = date_format($start_date, 'Ymd'); |
||
| 582 | |||
| 583 | date_add($end_date, date_interval_create_from_date_string('1 day')); |
||
| 584 | $dateend = date_format($end_date, 'Ymd'); |
||
| 585 | } |
||
| 586 | |||
| 587 | // This is what we will be sending later |
||
| 588 | $filecontents = ''; |
||
| 589 | $filecontents .= 'BEGIN:VCALENDAR' . "\n"; |
||
| 590 | $filecontents .= 'METHOD:PUBLISH' . "\n"; |
||
| 591 | $filecontents .= 'PRODID:-//SimpleMachines//SMF ' . (empty($forum_version) ? 2.1 : strtr($forum_version, array('SMF ' => ''))) . '//EN' . "\n"; |
||
| 592 | $filecontents .= 'VERSION:2.0' . "\n"; |
||
| 593 | $filecontents .= 'BEGIN:VEVENT' . "\n"; |
||
| 594 | // @TODO - Should be the members email who created the event rather than $webmaster_email. |
||
| 595 | $filecontents .= 'ORGANIZER;CN="' . $event['realname'] . '":MAILTO:' . $webmaster_email . "\n"; |
||
| 596 | $filecontents .= 'DTSTAMP:' . $datestamp . "\n"; |
||
| 597 | $filecontents .= 'DTSTART' . (!empty($event['start_time']) ? ';TZID=' . $event['tz'] : ';VALUE=DATE') . ':' . $datestart . "\n"; |
||
| 598 | |||
| 599 | // event has a duration |
||
| 600 | if ($event['start_iso_gmdate'] != $event['end_iso_gmdate']) |
||
| 601 | $filecontents .= 'DTEND' . (!empty($event['end_time']) ? ';TZID=' . $event['tz'] : ';VALUE=DATE') . ':' . $dateend . "\n"; |
||
| 602 | |||
| 603 | // event has changed? advance the sequence for this UID |
||
| 604 | if ($event['sequence'] > 0) |
||
| 605 | $filecontents .= 'SEQUENCE:' . $event['sequence'] . "\n"; |
||
| 606 | |||
| 607 | if (!empty($event['location'])) |
||
| 608 | $filecontents .= 'LOCATION:' . str_replace(',', '\,', $event['location']) . "\n"; |
||
| 609 | |||
| 610 | $filecontents .= 'SUMMARY:' . implode('', $title); |
||
| 611 | $filecontents .= 'UID:' . $event['eventid'] . '@' . str_replace(' ', '-', $mbname) . "\n"; |
||
| 612 | $filecontents .= 'END:VEVENT' . "\n"; |
||
| 613 | $filecontents .= 'END:VCALENDAR'; |
||
| 614 | |||
| 615 | // Send some standard headers. |
||
| 616 | ob_end_clean(); |
||
| 617 | if (!empty($modSettings['enableCompressedOutput'])) |
||
| 618 | @ob_start('ob_gzhandler'); |
||
|
0 ignored issues
–
show
|
|||
| 619 | else |
||
| 620 | ob_start(); |
||
| 621 | |||
| 622 | // Send the file headers |
||
| 623 | header('Pragma: '); |
||
| 624 | header('Cache-Control: no-cache'); |
||
| 625 | if (!isBrowser('gecko')) |
||
| 626 | header('Content-Transfer-Encoding: binary'); |
||
| 627 | header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT'); |
||
| 628 | header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . 'GMT'); |
||
| 629 | header('Accept-Ranges: bytes'); |
||
| 630 | header('Connection: close'); |
||
| 631 | header('Content-Disposition: attachment; filename="' . $event['title'] . '.ics"'); |
||
| 632 | if (empty($modSettings['enableCompressedOutput'])) |
||
| 633 | header('Content-Length: ' . $smcFunc['strlen']($filecontents)); |
||
| 634 | |||
| 635 | // This is a calendar item! |
||
| 636 | header('Content-Type: text/calendar'); |
||
| 637 | |||
| 638 | // Chuck out the card. |
||
| 639 | echo $filecontents; |
||
| 640 | |||
| 641 | // Off we pop - lovely! |
||
| 642 | obExit(false); |
||
| 643 | } |
||
| 644 | |||
| 645 | /** |
||
| 646 | * Nothing to see here. Move along. |
||
| 647 | */ |
||
| 648 | function clock() |
||
| 649 | { |
||
| 650 | global $smcFunc, $settings, $context, $scripturl; |
||
| 651 | |||
| 652 | $context['onimg'] = $settings['images_url'] . '/bbc/bbc_bg.png'; |
||
| 653 | $context['offimg'] = $settings['images_url'] . '/bbc/bbc_hoverbg.png'; |
||
| 654 | |||
| 655 | $context['page_title'] = 'Anyone know what time it is?'; |
||
| 656 | $context['linktree'][] = array( |
||
| 657 | 'url' => $scripturl . '?action=clock', |
||
| 658 | 'name' => 'Clock', |
||
| 659 | ); |
||
| 660 | $context['robot_no_index'] = true; |
||
| 661 | |||
| 662 | $omfg = isset($_REQUEST['omfg']); |
||
| 663 | $bcd = !isset($_REQUEST['rb']) && !isset($_REQUEST['omfg']) && !isset($_REQUEST['time']); |
||
| 664 | |||
| 665 | loadTemplate('Calendar'); |
||
| 666 | |||
| 667 | if ($bcd) |
||
| 668 | { |
||
| 669 | $context['sub_template'] = 'bcd'; |
||
| 670 | $context['linktree'][] = array('url' => $scripturl . '?action=clock;bcd', 'name' => 'BCD'); |
||
| 671 | $context['clockicons'] = $smcFunc['json_decode'](base64_decode('eyJoMSI6WzIsMV0sImgyIjpbOCw0LDIsMV0sIm0xIjpbNCwyLDFdLCJtMiI6WzgsNCwyLDFdLCJzMSI6WzQsMiwxXSwiczIiOls4LDQsMiwxXX0='), true); |
||
| 672 | } |
||
| 673 | View Code Duplication | elseif (!$omfg && !isset($_REQUEST['time'])) |
|
| 674 | { |
||
| 675 | $context['sub_template'] = 'hms'; |
||
| 676 | $context['linktree'][] = array('url' => $scripturl . '?action=clock', 'name' => 'Binary'); |
||
| 677 | $context['clockicons'] = $smcFunc['json_decode'](base64_decode('eyJoIjpbMTYsOCw0LDIsMV0sIm0iOlszMiwxNiw4LDQsMiwxXSwicyI6WzMyLDE2LDgsNCwyLDFdfQ'), true); |
||
| 678 | } |
||
| 679 | View Code Duplication | elseif ($omfg) |
|
| 680 | { |
||
| 681 | $context['sub_template'] = 'omfg'; |
||
| 682 | $context['linktree'][] = array('url' => $scripturl . '?action=clock;omfg', 'name' => 'OMFG'); |
||
| 683 | $context['clockicons'] = $smcFunc['json_decode'](base64_decode('eyJ5ZWFyIjpbNjQsMzIsMTYsOCw0LDIsMV0sIm1vbnRoIjpbOCw0LDIsMV0sImRheSI6WzE2LDgsNCwyLDFdLCJob3VyIjpbMTYsOCw0LDIsMV0sIm1pbiI6WzMyLDE2LDgsNCwyLDFdLCJzZWMiOlszMiwxNiw4LDQsMiwxXX0='), true); |
||
| 684 | } |
||
| 685 | elseif (isset($_REQUEST['time'])) |
||
| 686 | { |
||
| 687 | $context['sub_template'] = 'thetime'; |
||
| 688 | $time = getdate($_REQUEST['time'] == 'now' ? time() : (int) $_REQUEST['time']); |
||
| 689 | $context['linktree'][] = array('url' => $scripturl . '?action=clock;time=' . $_REQUEST['time'], 'name' => 'Requested Time'); |
||
| 690 | $context['clockicons'] = array( |
||
| 691 | 'year' => array( |
||
| 692 | 64 => false, |
||
| 693 | 32 => false, |
||
| 694 | 16 => false, |
||
| 695 | 8 => false, |
||
| 696 | 4 => false, |
||
| 697 | 2 => false, |
||
| 698 | 1 => false |
||
| 699 | ), |
||
| 700 | 'month' => array( |
||
| 701 | 8 => false, |
||
| 702 | 4 => false, |
||
| 703 | 2 => false, |
||
| 704 | 1 => false |
||
| 705 | ), |
||
| 706 | 'day' => array( |
||
| 707 | 16 => false, |
||
| 708 | 4 => false, |
||
| 709 | 8 => false, |
||
| 710 | 2 => false, |
||
| 711 | 1 => false |
||
| 712 | ), |
||
| 713 | 'hour' => array( |
||
| 714 | 32 => false, |
||
| 715 | 16 => false, |
||
| 716 | 8 => false, |
||
| 717 | 4 => false, |
||
| 718 | 2 => false, |
||
| 719 | 1 => false |
||
| 720 | ), |
||
| 721 | 'min' => array( |
||
| 722 | 32 => false, |
||
| 723 | 16 => false, |
||
| 724 | 8 => false, |
||
| 725 | 4 => false, |
||
| 726 | 2 => false, |
||
| 727 | 1 => false |
||
| 728 | ), |
||
| 729 | 'sec' => array( |
||
| 730 | 32 => false, |
||
| 731 | 16 => false, |
||
| 732 | 8 => false, |
||
| 733 | 4 => false, |
||
| 734 | 2 => false, |
||
| 735 | 1 => false |
||
| 736 | ), |
||
| 737 | ); |
||
| 738 | |||
| 739 | foreach ($context['clockicons'] as $t => $vs) |
||
| 740 | foreach ($vs as $v => $dumb) |
||
| 741 | { |
||
| 742 | if ($$t >= $v) |
||
| 743 | { |
||
| 744 | $$t -= $v; |
||
| 745 | $context['clockicons'][$t][$v] = true; |
||
| 746 | } |
||
| 747 | } |
||
| 748 | } |
||
| 749 | } |
||
| 750 | |||
| 751 | ?> |
If you suppress an error, we recommend checking for the error condition explicitly: