iCalDownload()   F
last analyzed

Complexity

Conditions 19
Paths 9216

Size

Total Lines 104
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
eloc 62
nop 0
dl 0
loc 104
rs 0.3499
c 0
b 0
f 0
nc 9216

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 2019 Simple Machines and individual contributors
12
 * @license http://www.simplemachines.org/about/smf/license.php BSD
13
 *
14
 * @version 2.1 RC2
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
 *
30
 * @return void
31
 */
32
function CalendarMain()
33
{
34
	global $txt, $context, $modSettings, $scripturl, $options, $sourcedir, $user_info, $smcFunc;
35
36
	// Permissions, permissions, permissions.
37
	isAllowedTo('calendar_view');
38
39
	// Some global template resources.
40
	$context['calendar_resources'] = array(
41
		'min_year' => $modSettings['cal_minyear'],
42
		'max_year' => $modSettings['cal_maxyear'],
43
	);
44
45
	// Doing something other than calendar viewing?
46
	$subActions = array(
47
		'ical' => 'iCalDownload',
48
		'post' => 'CalendarPost',
49
	);
50
51
	if (isset($_GET['sa']) && isset($subActions[$_GET['sa']]))
52
		return call_helper($subActions[$_GET['sa']]);
53
54
	// You can't do anything if the calendar is off.
55
	if (empty($modSettings['cal_enabled']))
56
		fatal_lang_error('calendar_off', false);
57
58
	// This is gonna be needed...
59
	loadTemplate('Calendar');
60
	loadCSSFile('calendar.css', array('force_current' => false, 'validate' => true, 'rtl' => 'calendar.rtl.css'), 'smf_calendar');
61
62
	// Did the specify an individual event ID? If so, let's splice the year/month in to what we would otherwise be doing.
63
	if (isset($_GET['event']))
64
	{
65
		$evid = (int) $_GET['event'];
66
		if ($evid > 0)
67
		{
68
			$request = $smcFunc['db_query']('', '
69
				SELECT start_date
70
				FROM {db_prefix}calendar
71
				WHERE id_event = {int:event_id}',
72
				array(
73
					'event_id' => $evid,
74
				)
75
			);
76
			if ($row = $smcFunc['db_fetch_assoc']($request))
77
			{
78
				$_REQUEST['start_date'] = $row['start_date'];
79
80
				// We might use this later.
81
				$context['selected_event'] = $evid;
82
			}
83
			$smcFunc['db_free_result']($request);
84
		}
85
		unset ($_GET['event']);
86
	}
87
88
	// Set the page title to mention the calendar ;).
89
	$context['page_title'] = $txt['calendar'];
90
91
	// Ensure a default view is defined
92
	if (empty($options['calendar_default_view']))
93
		$options['calendar_default_view'] = 'viewlist';
94
95
	// What view do we want?
96
	if (isset($_GET['viewweek']))
97
		$context['calendar_view'] = 'viewweek';
98
	elseif (isset($_GET['viewmonth']))
99
		$context['calendar_view'] = 'viewmonth';
100
	elseif (isset($_GET['viewlist']))
101
		$context['calendar_view'] = 'viewlist';
102
	else
103
		$context['calendar_view'] = $options['calendar_default_view'];
104
105
	// Don't let search engines index the non-default calendar pages
106
	if ($context['calendar_view'] !== $options['calendar_default_view'])
107
		$context['robot_no_index'] = true;
108
109
	// Get the current day of month...
110
	require_once($sourcedir . '/Subs-Calendar.php');
111
	$today = getTodayInfo();
112
113
	// Need a start date for all views
114
	if (!empty($_REQUEST['start_date']))
115
	{
116
		$start_parsed = date_parse($_REQUEST['start_date']);
117
		if (empty($start_parsed['error_count']) && empty($start_parsed['warning_count']))
118
		{
119
			$_REQUEST['year'] = $start_parsed['year'];
120
			$_REQUEST['month'] = $start_parsed['month'];
121
			$_REQUEST['day'] = $start_parsed['day'];
122
		}
123
	}
124
	$year = !empty($_REQUEST['year']) ? (int) $_REQUEST['year'] : $today['year'];
125
	$month = !empty($_REQUEST['month']) ? (int) $_REQUEST['month'] : $today['month'];
126
	$day = !empty($_REQUEST['day']) ? (int) $_REQUEST['day'] : (!empty($_REQUEST['month']) ? 1 : $today['day']);
127
128
	$start_object = checkdate($month, $day, $year) === true ? date_create(implode('-', array($year, $month, $day))) : date_create(implode('-', array($today['year'], $today['month'], $today['day'])));
129
130
	// Need an end date for the list view
131
	if (!empty($_REQUEST['end_date']))
132
	{
133
		$end_parsed = date_parse($_REQUEST['end_date']);
134
		if (empty($end_parsed['error_count']) && empty($end_parsed['warning_count']))
135
		{
136
			$_REQUEST['end_year'] = $end_parsed['year'];
137
			$_REQUEST['end_month'] = $end_parsed['month'];
138
			$_REQUEST['end_day'] = $end_parsed['day'];
139
		}
140
	}
141
	$end_year = !empty($_REQUEST['end_year']) ? (int) $_REQUEST['end_year'] : null;
142
	$end_month = !empty($_REQUEST['end_month']) ? (int) $_REQUEST['end_month'] : null;
143
	$end_day = !empty($_REQUEST['end_day']) ? (int) $_REQUEST['end_day'] : null;
144
145
	$end_object = checkdate($end_month, $end_day, $end_year) === true ? date_create(implode('-', array($end_year, $end_month, $end_day))) : null;
146
147
	if (empty($end_object) || $start_object >= $end_object)
148
	{
149
		$num_days_shown = empty($modSettings['cal_days_for_index']) || $modSettings['cal_days_for_index'] < 1 ? 1 : $modSettings['cal_days_for_index'];
150
151
		$end_object = date_create(date_format($start_object, 'Y-m-d'));
152
153
		date_add($end_object, date_interval_create_from_date_string($num_days_shown . ' days'));
154
	}
155
156
	$curPage = array(
157
		'year' => date_format($start_object, 'Y'),
158
		'month' => date_format($start_object, 'n'),
159
		'day' => date_format($start_object, 'j'),
160
		'start_date' => date_format($start_object, 'Y-m-d'),
161
		'end_year' => date_format($end_object, 'Y'),
162
		'end_month' => date_format($end_object, 'n'),
163
		'end_day' => date_format($end_object, 'j'),
164
		'end_date' => date_format($end_object, 'Y-m-d'),
165
	);
166
167
	// Make sure the year and month are in valid ranges.
168
	if ($curPage['month'] < 1 || $curPage['month'] > 12)
169
		fatal_lang_error('invalid_month', false);
170
	if ($curPage['year'] < $modSettings['cal_minyear'] || $curPage['year'] > $modSettings['cal_maxyear'])
171
		fatal_lang_error('invalid_year', false);
172
	// If we have a day clean that too.
173
	if ($context['calendar_view'] != 'viewmonth')
174
	{
175
		$isValid = checkdate($curPage['month'], $curPage['day'], $curPage['year']);
176
		if (!$isValid)
177
			fatal_lang_error('invalid_day', false);
178
	}
179
180
	// Load all the context information needed to show the calendar grid.
181
	$calendarOptions = array(
182
		'start_day' => !empty($options['calendar_start_day']) ? $options['calendar_start_day'] : 0,
183
		'show_birthdays' => in_array($modSettings['cal_showbdays'], array(1, 2)),
184
		'show_events' => in_array($modSettings['cal_showevents'], array(1, 2)),
185
		'show_holidays' => in_array($modSettings['cal_showholidays'], array(1, 2)),
186
		'show_week_num' => true,
187
		'short_day_titles' => !empty($modSettings['cal_short_days']),
188
		'short_month_titles' => !empty($modSettings['cal_short_months']),
189
		'show_next_prev' => !empty($modSettings['cal_prev_next_links']),
190
		'show_week_links' => isset($modSettings['cal_week_links']) ? $modSettings['cal_week_links'] : 0,
191
	);
192
193
	// Load up the main view.
194
	if ($context['calendar_view'] == 'viewlist')
195
		$context['calendar_grid_main'] = getCalendarList($curPage['start_date'], $curPage['end_date'], $calendarOptions);
196
	elseif ($context['calendar_view'] == 'viewweek')
197
		$context['calendar_grid_main'] = getCalendarWeek($curPage['start_date'], $calendarOptions);
198
	else
199
		$context['calendar_grid_main'] = getCalendarGrid($curPage['start_date'], $calendarOptions);
200
201
	// Load up the previous and next months.
202
	$context['calendar_grid_current'] = getCalendarGrid($curPage['start_date'], $calendarOptions);
203
204
	// Only show previous month if it isn't pre-January of the min-year
205
	if ($context['calendar_grid_current']['previous_calendar']['year'] > $modSettings['cal_minyear'] || $curPage['month'] != 1)
206
		$context['calendar_grid_prev'] = getCalendarGrid($context['calendar_grid_current']['previous_calendar']['start_date'], $calendarOptions, true);
207
208
	// Only show next month if it isn't post-December of the max-year
209
	if ($context['calendar_grid_current']['next_calendar']['year'] < $modSettings['cal_maxyear'] || $curPage['month'] != 12)
210
		$context['calendar_grid_next'] = getCalendarGrid($context['calendar_grid_current']['next_calendar']['start_date'], $calendarOptions);
211
212
	// Basic template stuff.
213
	$context['allow_calendar_event'] = allowedTo('calendar_post');
214
215
	// If you don't allow events not linked to posts and you're not an admin, we have more work to do...
216
	if ($context['allow_calendar_event'] && empty($modSettings['cal_allow_unlinked']) && !$user_info['is_admin'])
217
	{
218
		$boards_can_post = boardsAllowedTo('post_new');
219
		$context['allow_calendar_event'] &= !empty($boards_can_post);
220
	}
221
222
	$context['can_post'] = $context['allow_calendar_event'];
223
	$context['current_day'] = $curPage['day'];
224
	$context['current_month'] = $curPage['month'];
225
	$context['current_year'] = $curPage['year'];
226
	$context['show_all_birthdays'] = isset($_GET['showbd']);
227
	$context['blocks_disabled'] = !empty($modSettings['cal_disable_prev_next']) ? 1 : 0;
228
229
	// Set the page title to mention the month or week, too
230
	if ($context['calendar_view'] != 'viewlist')
231
		$context['page_title'] .= ' - ' . ($context['calendar_view'] == 'viewweek' ? $context['calendar_grid_main']['week_title'] : $txt['months'][$context['current_month']] . ' ' . $context['current_year']);
232
233
	// Load up the linktree!
234
	$context['linktree'][] = array(
235
		'url' => $scripturl . '?action=calendar',
236
		'name' => $txt['calendar']
237
	);
238
	// Add the current month to the linktree.
239
	$context['linktree'][] = array(
240
		'url' => $scripturl . '?action=calendar;year=' . $context['current_year'] . ';month=' . $context['current_month'],
241
		'name' => $txt['months'][$context['current_month']] . ' ' . $context['current_year']
242
	);
243
	// If applicable, add the current week to the linktree.
244
	if ($context['calendar_view'] == 'viewweek')
245
		$context['linktree'][] = array(
246
			'url' => $scripturl . '?action=calendar;viewweek;year=' . $context['current_year'] . ';month=' . $context['current_month'] . ';day=' . $context['current_day'],
247
			'name' => $context['calendar_grid_main']['week_title'],
248
		);
249
250
	// Build the calendar button array.
251
	$context['calendar_buttons'] = array();
252
253
	if ($context['can_post'])
254
		$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']);
255
256
	// Allow mods to add additional buttons here
257
	call_integration_hook('integrate_calendar_buttons');
258
}
259
260
/**
261
 * This function processes posting/editing/deleting a calendar event.
262
 *
263
 * 	- calls {@link Post.php|Post() Post()} function if event is linked to a post.
264
 *  - calls {@link Subs-Calendar.php|insertEvent() insertEvent()} to insert the event if not linked to post.
265
 *
266
 * It requires the calendar_post permission to use.
267
 * It uses the event_post sub template in the Calendar template.
268
 * It is accessed with ?action=calendar;sa=post.
269
 */
270
function CalendarPost()
271
{
272
	global $context, $txt, $user_info, $sourcedir, $scripturl;
273
	global $modSettings, $topic, $smcFunc;
274
275
	// Well - can they?
276
	isAllowedTo('calendar_post');
277
278
	// We need these for all kinds of useful functions.
279
	require_once($sourcedir . '/Subs-Calendar.php');
280
	require_once($sourcedir . '/Subs.php');
281
282
	// Cast this for safety...
283
	if (isset($_REQUEST['eventid']))
284
		$_REQUEST['eventid'] = (int) $_REQUEST['eventid'];
285
286
	// We want a fairly compact version of the time, but as close as possible to the user's settings.
287
	$time_string = strtr(get_date_or_time_format('time'), array(
288
		'%I' => '%l',
289
		'%H' => '%k',
290
		'%S' => '',
291
		'%r' => '%l:%M %p',
292
		'%R' => '%k:%M',
293
		'%T' => '%l:%M',
294
	));
295
296
	// Submitting?
297
	if (isset($_POST[$context['session_var']], $_REQUEST['eventid']))
298
	{
299
		checkSession();
300
301
		// Validate the post...
302
		if (!isset($_POST['link_to_board']))
303
			validateEventPost();
304
305
		// If you're not allowed to edit any events, you have to be the poster.
306
		if ($_REQUEST['eventid'] > 0 && !allowedTo('calendar_edit_any'))
307
			isAllowedTo('calendar_edit_' . (!empty($user_info['id']) && getEventPoster($_REQUEST['eventid']) == $user_info['id'] ? 'own' : 'any'));
308
309
		// New - and directing?
310
		if (isset($_POST['link_to_board']) || empty($modSettings['cal_allow_unlinked']))
311
		{
312
			$_REQUEST['calendar'] = 1;
313
			require_once($sourcedir . '/Post.php');
314
			return Post();
315
		}
316
		// New...
317
		elseif ($_REQUEST['eventid'] == -1)
318
		{
319
			$eventOptions = array(
320
				'board' => 0,
321
				'topic' => 0,
322
				'title' => $smcFunc['substr']($_REQUEST['evtitle'], 0, 100),
323
				'location' => $smcFunc['substr']($_REQUEST['event_location'], 0, 255),
324
				'member' => $user_info['id'],
325
			);
326
			insertEvent($eventOptions);
327
		}
328
329
		// Deleting...
330
		elseif (isset($_REQUEST['deleteevent']))
331
			removeEvent($_REQUEST['eventid']);
332
333
		// ... or just update it?
334
		else
335
		{
336
			$eventOptions = array(
337
				'title' => $smcFunc['substr']($_REQUEST['evtitle'], 0, 100),
338
				'location' => $smcFunc['substr']($_REQUEST['event_location'], 0, 255),
339
			);
340
			modifyEvent($_REQUEST['eventid'], $eventOptions);
341
		}
342
343
		updateSettings(array(
344
			'calendar_updated' => time(),
345
		));
346
347
		// No point hanging around here now...
348
		if (isset($_POST['start_date']))
349
		{
350
			$d = date_parse($_POST['start_date']);
351
			$year = $d['year'];
352
			$month = $d['month'];
353
			$day = $d['day'];
354
		}
355
		elseif (isset($_POST['start_datetime']))
356
		{
357
			$d = date_parse($_POST['start_datetime']);
358
			$year = $d['year'];
359
			$month = $d['month'];
360
			$day = $d['day'];
361
		}
362
		else
363
		{
364
			$today = getdate();
365
			$year = isset($_POST['year']) ? $_POST['year'] : $today['year'];
366
			$month = isset($_POST['month']) ? $_POST['month'] : $today['mon'];
367
			$day = isset($_POST['day']) ? $_POST['day'] : $today['mday'];
368
		}
369
		redirectexit($scripturl . '?action=calendar;month=' . $month . ';year=' . $year . ';day=' . $day);
370
	}
371
372
	// If we are not enabled... we are not enabled.
373
	if (empty($modSettings['cal_allow_unlinked']) && empty($_REQUEST['eventid']))
374
	{
375
		$_REQUEST['calendar'] = 1;
376
		require_once($sourcedir . '/Post.php');
377
		return Post();
0 ignored issues
show
Bug introduced by
Are you sure the usage of Post() is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
378
	}
379
380
	// New?
381
	if (!isset($_REQUEST['eventid']))
382
	{
383
		$context['event'] = array(
384
			'boards' => array(),
385
			'board' => 0,
386
			'new' => 1,
387
			'eventid' => -1,
388
			'title' => '',
389
			'location' => '',
390
		);
391
392
		$eventDatetimes = getNewEventDatetimes();
393
		$context['event'] = array_merge($context['event'], $eventDatetimes);
394
395
		$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']));
396
	}
397
	else
398
	{
399
		$context['event'] = getEventProperties($_REQUEST['eventid']);
400
401
		if ($context['event'] === false)
402
			fatal_lang_error('no_access', false);
403
404
		// If it has a board, then they should be editing it within the topic.
405
		if (!empty($context['event']['topic']['id']) && !empty($context['event']['topic']['first_msg']))
406
		{
407
			// We load the board up, for a check on the board access rights...
408
			$topic = $context['event']['topic']['id'];
409
			loadBoard();
410
		}
411
412
		// Make sure the user is allowed to edit this event.
413
		if ($context['event']['member'] != $user_info['id'])
414
			isAllowedTo('calendar_edit_any');
415
		elseif (!allowedTo('calendar_edit_any'))
416
			isAllowedTo('calendar_edit_own');
417
	}
418
419
	// An all day event? Set up some nice defaults in case the user wants to change that
420
	if ($context['event']['allday'] == true)
421
	{
422
		$context['event']['tz'] = getUserTimezone();
423
		$context['event']['start_time'] = timeformat(time(), $time_string);
0 ignored issues
show
Bug introduced by
$time_string of type string is incompatible with the type boolean expected by parameter $show_today of timeformat(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

423
		$context['event']['start_time'] = timeformat(time(), /** @scrutinizer ignore-type */ $time_string);
Loading history...
424
		$context['event']['end_time'] = timeformat(time() + 3600, $time_string);
425
	}
426
	// Otherwise, just adjust these to look nice on the input form
427
	else
428
	{
429
		$context['event']['start_time'] = $context['event']['start_time_orig'];
430
		$context['event']['end_time'] = $context['event']['end_time_orig'];
431
	}
432
433
	// Need this so the user can select a timezone for the event.
434
	$context['all_timezones'] = smf_list_timezones($context['event']['start_date']);
435
	unset($context['all_timezones']['']);
436
437
	// If the event's timezone is not in SMF's standard list of time zones, prepend it to the list
438
	if (!in_array($context['event']['tz'], array_keys($context['all_timezones'])))
439
	{
440
		$d = date_create($context['event']['start_datetime'] . ' ' . $context['event']['tz']);
441
		$context['all_timezones'] = array($context['event']['tz'] => '[UTC' . date_format($d, 'P') . '] - ' . $context['event']['tz']) + $context['all_timezones'];
442
	}
443
444
	// Get list of boards that can be posted in.
445
	$boards = boardsAllowedTo('post_new');
446
	if (empty($boards))
447
	{
448
		// You can post new events but can't link them to anything...
449
		$context['event']['categories'] = array();
450
	}
451
	else
452
	{
453
		// Load the list of boards and categories in the context.
454
		require_once($sourcedir . '/Subs-MessageIndex.php');
455
		$boardListOptions = array(
456
			'included_boards' => in_array(0, $boards) ? null : $boards,
457
			'not_redirection' => true,
458
			'use_permissions' => true,
459
			'selected_board' => $modSettings['cal_defaultboard'],
460
		);
461
		$context['event']['categories'] = getBoardList($boardListOptions);
462
	}
463
464
	// Template, sub template, etc.
465
	loadTemplate('Calendar');
466
	$context['sub_template'] = 'event_post';
467
468
	$context['page_title'] = isset($_REQUEST['eventid']) ? $txt['calendar_edit'] : $txt['calendar_post_event'];
469
	$context['linktree'][] = array(
470
		'name' => $context['page_title'],
471
	);
472
473
	loadDatePicker('#event_time_input .date_input');
474
	loadTimePicker('#event_time_input .time_input', $time_string);
475
	loadDatePair('#event_time_input', 'date_input', 'time_input');
476
	addInlineJavaScript('
477
	$("#allday").click(function(){
478
		$("#start_time").attr("disabled", this.checked);
479
		$("#end_time").attr("disabled", this.checked);
480
		$("#tz").attr("disabled", this.checked);
481
	});', true);
482
}
483
484
/**
485
 * This function offers up a download of an event in iCal 2.0 format.
486
 *
487
 * Follows the conventions in {@link https://tools.ietf.org/html/rfc5546 RFC5546}
488
 * Sets events as all day events since we don't have hourly events
489
 * Will honor and set multi day events
490
 * Sets a sequence number if the event has been modified
491
 *
492
 * @todo .... allow for week or month export files as well?
493
 */
494
function iCalDownload()
495
{
496
	global $smcFunc, $sourcedir, $modSettings, $webmaster_email, $mbname;
497
498
	// You can't export if the calendar export feature is off.
499
	if (empty($modSettings['cal_export']))
500
		fatal_lang_error('calendar_export_off', false);
501
502
	// Goes without saying that this is required.
503
	if (!isset($_REQUEST['eventid']))
504
		fatal_lang_error('no_access', false);
505
506
	// This is kinda wanted.
507
	require_once($sourcedir . '/Subs-Calendar.php');
508
509
	// Load up the event in question and check it exists.
510
	$event = getEventProperties($_REQUEST['eventid']);
511
512
	if ($event === false)
0 ignored issues
show
introduced by
The condition $event === false is always false.
Loading history...
513
		fatal_lang_error('no_access', false);
514
515
	// Check the title isn't too long - iCal requires some formatting if so.
516
	$title = str_split($event['title'], 30);
517
	foreach ($title as $id => $line)
518
	{
519
		if ($id != 0)
520
			$title[$id] = ' ' . $title[$id];
521
		$title[$id] .= "\n";
522
	}
523
524
	// Format the dates.
525
	$datestamp = date('Ymd\THis\Z', time());
526
	$start_date = date_create($event['start_date'] . (isset($event['start_time']) ? ' ' . $event['start_time'] : '') . (isset($event['tz']) ? ' ' . $event['tz'] : ''));
527
	$end_date = date_create($event['end_date'] . (isset($event['end_time']) ? ' ' . $event['end_time'] : '') . (isset($event['tz']) ? ' ' . $event['tz'] : ''));
528
529
	if (!empty($event['start_time']))
530
	{
531
		$datestart = date_format($start_date, 'Ymd\THis');
532
		$dateend = date_format($end_date, 'Ymd\THis');
533
	}
534
	else
535
	{
536
		$datestart = date_format($start_date, 'Ymd');
537
538
		date_add($end_date, date_interval_create_from_date_string('1 day'));
0 ignored issues
show
Bug introduced by
It seems like $end_date can also be of type false; however, parameter $object of date_add() does only seem to accept DateTime, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

538
		date_add(/** @scrutinizer ignore-type */ $end_date, date_interval_create_from_date_string('1 day'));
Loading history...
539
		$dateend = date_format($end_date, 'Ymd');
540
	}
541
542
	// This is what we will be sending later
543
	$filecontents = '';
544
	$filecontents .= 'BEGIN:VCALENDAR' . "\n";
545
	$filecontents .= 'METHOD:PUBLISH' . "\n";
546
	$filecontents .= 'PRODID:-//SimpleMachines//' . SMF_FULL_VERSION . '//EN' . "\n";
547
	$filecontents .= 'VERSION:2.0' . "\n";
548
	$filecontents .= 'BEGIN:VEVENT' . "\n";
549
	// @TODO - Should be the members email who created the event rather than $webmaster_email.
550
	$filecontents .= 'ORGANIZER;CN="' . $event['realname'] . '":MAILTO:' . $webmaster_email . "\n";
551
	$filecontents .= 'DTSTAMP:' . $datestamp . "\n";
552
	$filecontents .= 'DTSTART' . (!empty($event['start_time']) ? ';TZID=' . $event['tz'] : ';VALUE=DATE') . ':' . $datestart . "\n";
553
554
	// event has a duration
555
	if ($event['start_iso_gmdate'] != $event['end_iso_gmdate'])
556
		$filecontents .= 'DTEND' . (!empty($event['end_time']) ? ';TZID=' . $event['tz'] : ';VALUE=DATE') . ':' . $dateend . "\n";
557
558
	// event has changed? advance the sequence for this UID
559
	if ($event['sequence'] > 0)
560
		$filecontents .= 'SEQUENCE:' . $event['sequence'] . "\n";
561
562
	if (!empty($event['location']))
563
		$filecontents .= 'LOCATION:' . str_replace(',', '\,', $event['location']) . "\n";
564
565
	$filecontents .= 'SUMMARY:' . implode('', $title);
566
	$filecontents .= 'UID:' . $event['eventid'] . '@' . str_replace(' ', '-', $mbname) . "\n";
567
	$filecontents .= 'END:VEVENT' . "\n";
568
	$filecontents .= 'END:VCALENDAR';
569
570
	// Send some standard headers.
571
	ob_end_clean();
572
	if (!empty($modSettings['enableCompressedOutput']))
573
		@ob_start('ob_gzhandler');
574
	else
575
		ob_start();
576
577
	// Send the file headers
578
	header('pragma: ');
579
	header('cache-control: no-cache');
580
	if (!isBrowser('gecko'))
581
		header('content-transfer-encoding: binary');
582
	header('expires: ' . gmdate('D, d M Y H:i:s', time() + 525600 * 60) . ' GMT');
583
	header('last-modified: ' . gmdate('D, d M Y H:i:s', time()) . 'GMT');
584
	header('accept-ranges: bytes');
585
	header('connection: close');
586
	header('content-disposition: attachment; filename="' . $event['title'] . '.ics"');
587
	if (empty($modSettings['enableCompressedOutput']))
588
		header('content-length: ' . $smcFunc['strlen']($filecontents));
589
590
	// This is a calendar item!
591
	header('content-type: text/calendar');
592
593
	// Chuck out the card.
594
	echo $filecontents;
595
596
	// Off we pop - lovely!
597
	obExit(false);
598
}
599
600
/**
601
 * Nothing to see here. Move along.
602
 */
603
function clock()
604
{
605
	global $smcFunc, $settings, $context, $scripturl;
606
607
	$context['onimg'] = $settings['images_url'] . '/bbc/bbc_hoverbg.png';
608
	$context['offimg'] = $settings['images_url'] . '/bbc/bbc_bg.png';
609
610
	$context['page_title'] = 'Anyone know what time it is?';
611
	$context['linktree'][] = array(
612
		'url' => $scripturl . '?action=clock',
613
		'name' => 'Clock',
614
	);
615
	$context['robot_no_index'] = true;
616
617
	$omfg = isset($_REQUEST['omfg']);
618
	$bcd = !isset($_REQUEST['rb']) && !isset($_REQUEST['omfg']) && !isset($_REQUEST['time']);
619
620
	loadTemplate('Calendar');
621
622
	if ($bcd)
623
	{
624
		$context['sub_template'] = 'bcd';
625
		$context['linktree'][] = array('url' => $scripturl . '?action=clock;bcd', 'name' => 'BCD');
626
		$context['clockicons'] = $smcFunc['json_decode'](base64_decode('eyJoMSI6WzIsMV0sImgyIjpbOCw0LDIsMV0sIm0xIjpbNCwyLDFdLCJtMiI6WzgsNCwyLDFdLCJzMSI6WzQsMiwxXSwiczIiOls4LDQsMiwxXX0='), true);
627
	}
628
	elseif (!$omfg && !isset($_REQUEST['time']))
629
	{
630
		$context['sub_template'] = 'hms';
631
		$context['linktree'][] = array('url' => $scripturl . '?action=clock', 'name' => 'Binary');
632
		$context['clockicons'] = $smcFunc['json_decode'](base64_decode('eyJoIjpbMTYsOCw0LDIsMV0sIm0iOlszMiwxNiw4LDQsMiwxXSwicyI6WzMyLDE2LDgsNCwyLDFdfQ'), true);
633
	}
634
	elseif ($omfg)
635
	{
636
		$context['sub_template'] = 'omfg';
637
		$context['linktree'][] = array('url' => $scripturl . '?action=clock;omfg', 'name' => 'OMFG');
638
		$context['clockicons'] = $smcFunc['json_decode'](base64_decode('eyJ5ZWFyIjpbNjQsMzIsMTYsOCw0LDIsMV0sIm1vbnRoIjpbOCw0LDIsMV0sImRheSI6WzE2LDgsNCwyLDFdLCJob3VyIjpbMTYsOCw0LDIsMV0sIm1pbiI6WzMyLDE2LDgsNCwyLDFdLCJzZWMiOlszMiwxNiw4LDQsMiwxXX0='), true);
639
	}
640
	elseif (isset($_REQUEST['time']))
641
	{
642
		$context['sub_template'] = 'thetime';
643
		$time = getdate($_REQUEST['time'] == 'now' ? time() : (int) $_REQUEST['time']);
644
		$context['linktree'][] = array('url' => $scripturl . '?action=clock;time=' . $_REQUEST['time'], 'name' => 'Requested Time');
645
		$context['clockicons'] = array(
646
			'year' => array(
647
				64 => false,
648
				32 => false,
649
				16 => false,
650
				8 => false,
651
				4 => false,
652
				2 => false,
653
				1 => false
654
			),
655
			'month' => array(
656
				8 => false,
657
				4 => false,
658
				2 => false,
659
				1 => false
660
			),
661
			'day' => array(
662
				16 => false,
663
				4 => false,
664
				8 => false,
665
				2 => false,
666
				1 => false
667
			),
668
			'hour' => array(
669
				32 => false,
670
				16 => false,
671
				8 => false,
672
				4 => false,
673
				2 => false,
674
				1 => false
675
			),
676
			'min' => array(
677
				32 => false,
678
				16 => false,
679
				8 => false,
680
				4 => false,
681
				2 => false,
682
				1 => false
683
			),
684
			'sec' => array(
685
				32 => false,
686
				16 => false,
687
				8 => false,
688
				4 => false,
689
				2 => false,
690
				1 => false
691
			),
692
		);
693
694
		foreach ($context['clockicons'] as $t => $vs)
695
			foreach ($vs as $v => $dumb)
696
			{
697
				if ($$t >= $v)
698
				{
699
					$$t -= $v;
700
					$context['clockicons'][$t][$v] = true;
701
				}
702
			}
703
	}
704
}
705
706
?>