1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file contains several functions for retrieving and manipulating calendar events, birthdays and holidays. |
5
|
|
|
* |
6
|
|
|
* Simple Machines Forum (SMF) |
7
|
|
|
* |
8
|
|
|
* @package SMF |
9
|
|
|
* @author Simple Machines http://www.simplemachines.org |
10
|
|
|
* @copyright 2017 Simple Machines and individual contributors |
11
|
|
|
* @license http://www.simplemachines.org/about/smf/license.php BSD |
12
|
|
|
* |
13
|
|
|
* @version 2.1 Beta 3 |
14
|
|
|
*/ |
15
|
|
|
|
16
|
|
|
if (!defined('SMF')) |
17
|
|
|
die('No direct access...'); |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Get all birthdays within the given time range. |
21
|
|
|
* finds all the birthdays in the specified range of days. |
22
|
|
|
* works with birthdays set for no year, or any other year, and respects month and year boundaries. |
23
|
|
|
* |
24
|
|
|
* @param string $low_date The low end of the range, inclusive, in YYYY-MM-DD format |
25
|
|
|
* @param string $high_date The high end of the range, inclusive, in YYYY-MM-DD format |
26
|
|
|
* @return array An array of days, each of which is an array of birthday information for the context |
27
|
|
|
*/ |
28
|
|
|
function getBirthdayRange($low_date, $high_date) |
29
|
|
|
{ |
30
|
|
|
global $smcFunc; |
31
|
|
|
|
32
|
|
|
// We need to search for any birthday in this range, and whatever year that birthday is on. |
33
|
|
|
$year_low = (int) substr($low_date, 0, 4); |
34
|
|
|
$year_high = (int) substr($high_date, 0, 4); |
35
|
|
|
|
36
|
|
|
if ($smcFunc['db_title'] != "PostgreSQL") |
37
|
|
|
{ |
38
|
|
|
// Collect all of the birthdays for this month. I know, it's a painful query. |
39
|
|
|
$result = $smcFunc['db_query']('birthday_array', ' |
40
|
|
|
SELECT id_member, real_name, YEAR(birthdate) AS birth_year, birthdate |
41
|
|
|
FROM {db_prefix}members |
42
|
|
|
WHERE YEAR(birthdate) != {string:year_one} |
43
|
|
|
AND MONTH(birthdate) != {int:no_month} |
44
|
|
|
AND DAYOFMONTH(birthdate) != {int:no_day} |
45
|
|
|
AND YEAR(birthdate) <= {int:max_year} |
46
|
|
|
AND ( |
47
|
|
|
DATE_FORMAT(birthdate, {string:year_low}) BETWEEN {date:low_date} AND {date:high_date}' . ($year_low == $year_high ? '' : ' |
48
|
|
|
OR DATE_FORMAT(birthdate, {string:year_high}) BETWEEN {date:low_date} AND {date:high_date}') . ' |
49
|
|
|
) |
50
|
|
|
AND is_activated = {int:is_activated}', |
51
|
|
|
array( |
52
|
|
|
'is_activated' => 1, |
53
|
|
|
'no_month' => 0, |
54
|
|
|
'no_day' => 0, |
55
|
|
|
'year_one' => '0001', |
56
|
|
|
'year_low' => $year_low . '-%m-%d', |
57
|
|
|
'year_high' => $year_high . '-%m-%d', |
58
|
|
|
'low_date' => $low_date, |
59
|
|
|
'high_date' => $high_date, |
60
|
|
|
'max_year' => $year_high, |
61
|
|
|
) |
62
|
|
|
); |
63
|
|
|
} |
64
|
|
|
else |
65
|
|
|
{ |
66
|
|
|
$result = $smcFunc['db_query']('birthday_array', ' |
67
|
|
|
SELECT id_member, real_name, YEAR(birthdate) AS birth_year, birthdate |
68
|
|
|
FROM {db_prefix}members |
69
|
|
|
WHERE YEAR(birthdate) != {string:year_one} |
70
|
|
|
AND MONTH(birthdate) != {int:no_month} |
71
|
|
|
AND DAYOFMONTH(birthdate) != {int:no_day} |
72
|
|
|
AND ( |
73
|
|
|
indexable_month_day(birthdate) BETWEEN indexable_month_day({date:year_low_low_date}) AND indexable_month_day({date:year_low_high_date})' . ($year_low == $year_high ? '' : ' |
74
|
|
|
OR indexable_month_day(birthdate) BETWEEN indexable_month_day({date:year_high_low_date}) AND indexable_month_day({date:year_high_high_date})') . ' |
75
|
|
|
) |
76
|
|
|
AND is_activated = {int:is_activated}', |
77
|
|
|
array( |
78
|
|
|
'is_activated' => 1, |
79
|
|
|
'no_month' => 0, |
80
|
|
|
'no_day' => 0, |
81
|
|
|
'year_one' => '0001', |
82
|
|
|
'year_low' => $year_low . '-%m-%d', |
83
|
|
|
'year_high' => $year_high . '-%m-%d', |
84
|
|
|
'year_low_low_date' => $low_date, |
85
|
|
|
'year_low_high_date' => ($year_low == $year_high ? $high_date : $year_low . '-12-31'), |
86
|
|
|
'year_high_low_date' => ($year_low == $year_high ? $low_date : $year_high . '-01-01'), |
87
|
|
|
'year_high_high_date' => $high_date, |
88
|
|
|
) |
89
|
|
|
); |
90
|
|
|
} |
91
|
|
|
$bday = array(); |
92
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
93
|
|
|
{ |
94
|
|
|
if ($year_low != $year_high) |
95
|
|
|
$age_year = substr($row['birthdate'], 5) < substr($high_date, 5) ? $year_high : $year_low; |
96
|
|
|
else |
97
|
|
|
$age_year = $year_low; |
98
|
|
|
|
99
|
|
|
$bday[$age_year . substr($row['birthdate'], 4)][] = array( |
100
|
|
|
'id' => $row['id_member'], |
101
|
|
|
'name' => $row['real_name'], |
102
|
|
|
'age' => $row['birth_year'] > 4 && $row['birth_year'] <= $age_year ? $age_year - $row['birth_year'] : null, |
103
|
|
|
'is_last' => false |
104
|
|
|
); |
105
|
|
|
} |
106
|
|
|
$smcFunc['db_free_result']($result); |
107
|
|
|
|
108
|
|
|
ksort($bday); |
109
|
|
|
|
110
|
|
|
// Set is_last, so the themes know when to stop placing separators. |
111
|
|
View Code Duplication |
foreach ($bday as $mday => $array) |
|
|
|
|
112
|
|
|
$bday[$mday][count($array) - 1]['is_last'] = true; |
113
|
|
|
|
114
|
|
|
return $bday; |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
/** |
118
|
|
|
* Get all calendar events within the given time range. |
119
|
|
|
* |
120
|
|
|
* - finds all the posted calendar events within a date range. |
121
|
|
|
* - both the earliest_date and latest_date should be in the standard YYYY-MM-DD format. |
122
|
|
|
* - censors the posted event titles. |
123
|
|
|
* - uses the current user's permissions if use_permissions is true, otherwise it does nothing "permission specific" |
124
|
|
|
* |
125
|
|
|
* @param string $low_date The low end of the range, inclusive, in YYYY-MM-DD format |
126
|
|
|
* @param string $high_date The high end of the range, inclusive, in YYYY-MM-DD format |
127
|
|
|
* @param bool $use_permissions Whether to use permissions |
128
|
|
|
* @return array Contextual information if use_permissions is true, and an array of the data needed to build that otherwise |
129
|
|
|
*/ |
130
|
|
|
function getEventRange($low_date, $high_date, $use_permissions = true) |
131
|
|
|
{ |
132
|
|
|
global $scripturl, $modSettings, $user_info, $smcFunc, $context, $sourcedir; |
133
|
|
|
require_once($sourcedir . '/Subs.php'); |
134
|
|
|
|
135
|
|
|
$low_object = date_create($low_date); |
136
|
|
|
$high_object = date_create($high_date); |
137
|
|
|
|
138
|
|
|
// Find all the calendar info... |
139
|
|
|
$result = $smcFunc['db_query']('', ' |
140
|
|
|
SELECT |
141
|
|
|
cal.id_event, cal.title, cal.id_member, cal.id_topic, cal.id_board, |
142
|
|
|
cal.start_date, cal.end_date, cal.start_time, cal.end_time, cal.timezone, cal.location, |
143
|
|
|
b.member_groups, t.id_first_msg, t.approved, b.id_board |
144
|
|
|
FROM {db_prefix}calendar AS cal |
145
|
|
|
LEFT JOIN {db_prefix}boards AS b ON (b.id_board = cal.id_board) |
146
|
|
|
LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = cal.id_topic) |
147
|
|
|
WHERE cal.start_date <= {date:high_date} |
148
|
|
|
AND cal.end_date >= {date:low_date}' . ($use_permissions ? ' |
149
|
|
|
AND (cal.id_board = {int:no_board_link} OR {query_wanna_see_board})' : ''), |
150
|
|
|
array( |
151
|
|
|
'high_date' => $high_date, |
152
|
|
|
'low_date' => $low_date, |
153
|
|
|
'no_board_link' => 0, |
154
|
|
|
) |
155
|
|
|
); |
156
|
|
|
$events = array(); |
157
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
158
|
|
|
{ |
159
|
|
|
// If the attached topic is not approved then for the moment pretend it doesn't exist |
160
|
|
|
if (!empty($row['id_first_msg']) && $modSettings['postmod_active'] && !$row['approved']) |
161
|
|
|
continue; |
162
|
|
|
|
163
|
|
|
// Force a censor of the title - as often these are used by others. |
164
|
|
|
censorText($row['title'], $use_permissions ? false : true); |
165
|
|
|
|
166
|
|
|
// Get the various time and date properties for this event |
167
|
|
|
list($start, $end, $allday, $span, $tz, $tz_abbrev) = buildEventDatetimes($row); |
168
|
|
|
|
169
|
|
|
// Sanity check |
170
|
|
View Code Duplication |
if (!empty($start['error_count']) || !empty($start['warning_count']) || !empty($end['error_count']) || !empty($end['warning_count'])) |
|
|
|
|
171
|
|
|
continue; |
172
|
|
|
|
173
|
|
|
// Get set up for the loop |
174
|
|
|
$start_object = date_create($row['start_date'] . (!$allday ? ' ' . $row['start_time'] : ''), timezone_open($tz)); |
175
|
|
|
$end_object = date_create($row['end_date'] . (!$allday ? ' ' . $row['end_time'] : ''), timezone_open($tz)); |
176
|
|
|
date_timezone_set($start_object, timezone_open(date_default_timezone_get())); |
177
|
|
|
date_timezone_set($end_object, timezone_open(date_default_timezone_get())); |
178
|
|
|
date_time_set($start_object, 0, 0, 0); |
179
|
|
|
date_time_set($end_object, 0, 0, 0); |
180
|
|
|
$start_date_string = date_format($start_object, 'Y-m-d'); |
181
|
|
|
$end_date_string = date_format($end_object, 'Y-m-d'); |
182
|
|
|
|
183
|
|
|
$cal_date = ($start_object >= $low_object) ? $start_object : $low_object; |
184
|
|
|
while ($cal_date <= $end_object && $cal_date <= $high_object) |
185
|
|
|
{ |
186
|
|
|
$starts_today = (date_format($cal_date, 'Y-m-d') == $start_date_string); |
187
|
|
|
$ends_today = (date_format($cal_date, 'Y-m-d') == $end_date_string); |
188
|
|
|
|
189
|
|
|
$eventProperties = array( |
190
|
|
|
'id' => $row['id_event'], |
191
|
|
|
'title' => $row['title'], |
192
|
|
|
'year' => $start['year'], |
193
|
|
|
'month' => $start['month'], |
194
|
|
|
'day' => $start['day'], |
195
|
|
|
'hour' => !$allday ? $start['hour'] : null, |
196
|
|
|
'minute' => !$allday ? $start['minute'] : null, |
197
|
|
|
'second' => !$allday ? $start['second'] : null, |
198
|
|
|
'start_date' => $row['start_date'], |
199
|
|
|
'start_date_local' => $start['date_local'], |
200
|
|
|
'start_date_orig' => $start['date_orig'], |
201
|
|
|
'start_time' => !$allday ? $row['start_time'] : null, |
202
|
|
|
'start_time_local' => !$allday ? $start['time_local'] : null, |
203
|
|
|
'start_time_orig' => !$allday ? $start['time_orig'] : null, |
204
|
|
|
'start_timestamp' => $start['timestamp'], |
205
|
|
|
'start_datetime' => $start['datetime'], |
206
|
|
|
'start_iso_gmdate' => $start['iso_gmdate'], |
207
|
|
|
'end_year' => $end['year'], |
208
|
|
|
'end_month' => $end['month'], |
209
|
|
|
'end_day' => $end['day'], |
210
|
|
|
'end_hour' => !$allday ? $end['hour'] : null, |
211
|
|
|
'end_minute' => !$allday ? $end['minute'] : null, |
212
|
|
|
'end_second' => !$allday ? $end['second'] : null, |
213
|
|
|
'end_date' => $row['end_date'], |
214
|
|
|
'end_date_local' => $end['date_local'], |
215
|
|
|
'end_date_orig' => $end['date_orig'], |
216
|
|
|
'end_time' => !$allday ? $row['end_time'] : null, |
217
|
|
|
'end_time_local' => !$allday ? $end['time_local'] : null, |
218
|
|
|
'end_time_orig' => !$allday ? $end['time_orig'] : null, |
219
|
|
|
'end_timestamp' => $end['timestamp'], |
220
|
|
|
'end_datetime' => $end['datetime'], |
221
|
|
|
'end_iso_gmdate' => $end['iso_gmdate'], |
222
|
|
|
'allday' => $allday, |
223
|
|
|
'tz' => !$allday ? $tz : null, |
224
|
|
|
'tz_abbrev' => !$allday ? $tz_abbrev : null, |
225
|
|
|
'span' => $span, |
226
|
|
|
'is_last' => false, |
227
|
|
|
'id_board' => $row['id_board'], |
228
|
|
|
'is_selected' => !empty($context['selected_event']) && $context['selected_event'] == $row['id_event'], |
229
|
|
|
'starts_today' => $starts_today, |
230
|
|
|
'ends_today' => $ends_today, |
231
|
|
|
'location' => $row['location'], |
232
|
|
|
); |
233
|
|
|
|
234
|
|
|
// If we're using permissions (calendar pages?) then just ouput normal contextual style information. |
235
|
|
|
if ($use_permissions) |
236
|
|
|
$events[date_format($cal_date, 'Y-m-d')][] = array_merge($eventProperties, array( |
237
|
|
|
'href' => $row['id_board'] == 0 ? '' : $scripturl . '?topic=' . $row['id_topic'] . '.0', |
238
|
|
|
'link' => $row['id_board'] == 0 ? $row['title'] : '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['title'] . '</a>', |
239
|
|
|
'can_edit' => allowedTo('calendar_edit_any') || ($row['id_member'] == $user_info['id'] && allowedTo('calendar_edit_own')), |
240
|
|
|
'modify_href' => $scripturl . '?action=' . ($row['id_board'] == 0 ? 'calendar;sa=post;' : 'post;msg=' . $row['id_first_msg'] . ';topic=' . $row['id_topic'] . '.0;calendar;') . 'eventid=' . $row['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
241
|
|
|
'can_export' => !empty($modSettings['cal_export']) ? true : false, |
242
|
|
|
'export_href' => $scripturl . '?action=calendar;sa=ical;eventid=' . $row['id_event'] . ';' . $context['session_var'] . '=' . $context['session_id'], |
243
|
|
|
)); |
244
|
|
|
// Otherwise, this is going to be cached and the VIEWER'S permissions should apply... just put together some info. |
245
|
|
|
else |
246
|
|
|
$events[date_format($cal_date, 'Y-m-d')][] = array_merge($eventProperties, array( |
247
|
|
|
'href' => $row['id_topic'] == 0 ? '' : $scripturl . '?topic=' . $row['id_topic'] . '.0', |
248
|
|
|
'link' => $row['id_topic'] == 0 ? $row['title'] : '<a href="' . $scripturl . '?topic=' . $row['id_topic'] . '.0">' . $row['title'] . '</a>', |
249
|
|
|
'can_edit' => false, |
250
|
|
|
'can_export' => !empty($modSettings['cal_export']) ? true : false, |
251
|
|
|
'topic' => $row['id_topic'], |
252
|
|
|
'msg' => $row['id_first_msg'], |
253
|
|
|
'poster' => $row['id_member'], |
254
|
|
|
'allowed_groups' => explode(',', $row['member_groups']), |
255
|
|
|
)); |
256
|
|
|
|
257
|
|
|
date_add($cal_date, date_interval_create_from_date_string('1 day')); |
258
|
|
|
} |
259
|
|
|
} |
260
|
|
|
$smcFunc['db_free_result']($result); |
261
|
|
|
|
262
|
|
|
// If we're doing normal contextual data, go through and make things clear to the templates ;). |
263
|
|
|
if ($use_permissions) |
264
|
|
|
{ |
265
|
|
View Code Duplication |
foreach ($events as $mday => $array) |
|
|
|
|
266
|
|
|
$events[$mday][count($array) - 1]['is_last'] = true; |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
ksort($events); |
270
|
|
|
|
271
|
|
|
return $events; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Get all holidays within the given time range. |
276
|
|
|
* |
277
|
|
|
* @param string $low_date The low end of the range, inclusive, in YYYY-MM-DD format |
278
|
|
|
* @param string $high_date The high end of the range, inclusive, in YYYY-MM-DD format |
279
|
|
|
* @return array An array of days, which are all arrays of holiday names. |
280
|
|
|
*/ |
281
|
|
|
function getHolidayRange($low_date, $high_date) |
282
|
|
|
{ |
283
|
|
|
global $smcFunc; |
284
|
|
|
|
285
|
|
|
// Get the lowest and highest dates for "all years". |
286
|
|
|
if (substr($low_date, 0, 4) != substr($high_date, 0, 4)) |
287
|
|
|
$allyear_part = 'event_date BETWEEN {date:all_year_low} AND {date:all_year_dec} |
288
|
|
|
OR event_date BETWEEN {date:all_year_jan} AND {date:all_year_high}'; |
289
|
|
|
else |
290
|
|
|
$allyear_part = 'event_date BETWEEN {date:all_year_low} AND {date:all_year_high}'; |
291
|
|
|
|
292
|
|
|
// Find some holidays... ;). |
293
|
|
|
$result = $smcFunc['db_query']('', ' |
294
|
|
|
SELECT event_date, YEAR(event_date) AS year, title |
295
|
|
|
FROM {db_prefix}calendar_holidays |
296
|
|
|
WHERE event_date BETWEEN {date:low_date} AND {date:high_date} |
297
|
|
|
OR ' . $allyear_part, |
298
|
|
|
array( |
299
|
|
|
'low_date' => $low_date, |
300
|
|
|
'high_date' => $high_date, |
301
|
|
|
'all_year_low' => '0004' . substr($low_date, 4), |
302
|
|
|
'all_year_high' => '0004' . substr($high_date, 4), |
303
|
|
|
'all_year_jan' => '0004-01-01', |
304
|
|
|
'all_year_dec' => '0004-12-31', |
305
|
|
|
) |
306
|
|
|
); |
307
|
|
|
$holidays = array(); |
308
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($result)) |
309
|
|
|
{ |
310
|
|
|
if (substr($low_date, 0, 4) != substr($high_date, 0, 4)) |
311
|
|
|
$event_year = substr($row['event_date'], 5) < substr($high_date, 5) ? substr($high_date, 0, 4) : substr($low_date, 0, 4); |
312
|
|
|
else |
313
|
|
|
$event_year = substr($low_date, 0, 4); |
314
|
|
|
|
315
|
|
|
$holidays[$event_year . substr($row['event_date'], 4)][] = $row['title']; |
316
|
|
|
} |
317
|
|
|
$smcFunc['db_free_result']($result); |
318
|
|
|
|
319
|
|
|
ksort($holidays); |
320
|
|
|
|
321
|
|
|
return $holidays; |
322
|
|
|
} |
323
|
|
|
|
324
|
|
|
/** |
325
|
|
|
* Does permission checks to see if an event can be linked to a board/topic. |
326
|
|
|
* checks if the current user can link the current topic to the calendar, permissions et al. |
327
|
|
|
* this requires the calendar_post permission, a forum moderator, or a topic starter. |
328
|
|
|
* expects the $topic and $board variables to be set. |
329
|
|
|
* if the user doesn't have proper permissions, an error will be shown. |
330
|
|
|
*/ |
331
|
|
|
function canLinkEvent() |
332
|
|
|
{ |
333
|
|
|
global $user_info, $topic, $board, $smcFunc; |
334
|
|
|
|
335
|
|
|
// If you can't post, you can't link. |
336
|
|
|
isAllowedTo('calendar_post'); |
337
|
|
|
|
338
|
|
|
// No board? No topic?!? |
339
|
|
|
if (empty($board)) |
340
|
|
|
fatal_lang_error('missing_board_id', false); |
341
|
|
|
if (empty($topic)) |
342
|
|
|
fatal_lang_error('missing_topic_id', false); |
343
|
|
|
|
344
|
|
|
// Administrator, Moderator, or owner. Period. |
345
|
|
|
if (!allowedTo('admin_forum') && !allowedTo('moderate_board')) |
346
|
|
|
{ |
347
|
|
|
// Not admin or a moderator of this board. You better be the owner - or else. |
348
|
|
|
$result = $smcFunc['db_query']('', ' |
349
|
|
|
SELECT id_member_started |
350
|
|
|
FROM {db_prefix}topics |
351
|
|
|
WHERE id_topic = {int:current_topic} |
352
|
|
|
LIMIT 1', |
353
|
|
|
array( |
354
|
|
|
'current_topic' => $topic, |
355
|
|
|
) |
356
|
|
|
); |
357
|
|
|
if ($row = $smcFunc['db_fetch_assoc']($result)) |
358
|
|
|
{ |
359
|
|
|
// Not the owner of the topic. |
360
|
|
|
if ($row['id_member_started'] != $user_info['id']) |
361
|
|
|
fatal_lang_error('not_your_topic', 'user'); |
362
|
|
|
} |
363
|
|
|
// Topic/Board doesn't exist..... |
364
|
|
|
else |
365
|
|
|
fatal_lang_error('calendar_no_topic', 'general'); |
366
|
|
|
$smcFunc['db_free_result']($result); |
367
|
|
|
} |
368
|
|
|
} |
369
|
|
|
|
370
|
|
|
/** |
371
|
|
|
* Returns date information about 'today' relative to the users time offset. |
372
|
|
|
* returns an array with the current date, day, month, and year. |
373
|
|
|
* takes the users time offset into account. |
374
|
|
|
* @return array An array of info about today, based on forum time. Has 'day', 'month', 'year' and 'date' (in YYYY-MM-DD format) |
375
|
|
|
*/ |
376
|
|
|
function getTodayInfo() |
377
|
|
|
{ |
378
|
|
|
return array( |
379
|
|
|
'day' => (int) strftime('%d', forum_time()), |
380
|
|
|
'month' => (int) strftime('%m', forum_time()), |
381
|
|
|
'year' => (int) strftime('%Y', forum_time()), |
382
|
|
|
'date' => strftime('%Y-%m-%d', forum_time()), |
383
|
|
|
); |
384
|
|
|
} |
385
|
|
|
|
386
|
|
|
/** |
387
|
|
|
* Provides information (link, month, year) about the previous and next month. |
388
|
|
|
* @param int $month The month to display |
389
|
|
|
* @param int $year The year |
390
|
|
|
* @param array $calendarOptions An array of calendar options |
391
|
|
|
* @param bool $is_previous Whether this is the previous month |
392
|
|
|
* @return array A large array containing all the information needed to show a calendar grid for the given month |
393
|
|
|
*/ |
394
|
|
|
function getCalendarGrid($month, $year, $calendarOptions, $is_previous = false) |
395
|
|
|
{ |
396
|
|
|
global $scripturl, $modSettings; |
397
|
|
|
|
398
|
|
|
// Eventually this is what we'll be returning. |
399
|
|
|
$calendarGrid = array( |
400
|
|
|
'week_days' => array(), |
401
|
|
|
'weeks' => array(), |
402
|
|
|
'short_day_titles' => !empty($calendarOptions['short_day_titles']), |
403
|
|
|
'short_month_titles' => !empty($calendarOptions['short_month_titles']), |
404
|
|
|
'highlight' => array( |
405
|
|
|
'events' => !empty($calendarOptions['highlight']['events']) && !empty($calendarOptions['show_events']) ? $calendarOptions['highlight']['events'] : 0, |
406
|
|
|
'holidays' => !empty($calendarOptions['highlight']['holidays']) && !empty($calendarOptions['show_holidays']) ? $calendarOptions['highlight']['holidays'] : 0, |
407
|
|
|
'birthdays' => !empty($calendarOptions['highlight']['birthdays']) && !empty($calendarOptions['show_birthdays']) ? $calendarOptions['highlight']['birthdays'] : 0, |
408
|
|
|
), |
409
|
|
|
'current_month' => $month, |
410
|
|
|
'current_year' => $year, |
411
|
|
|
'show_next_prev' => !empty($calendarOptions['show_next_prev']), |
412
|
|
|
'show_week_links' => isset($calendarOptions['show_week_links']) ? $calendarOptions['show_week_links'] : 0, |
413
|
|
|
'previous_calendar' => array( |
414
|
|
|
'year' => $month == 1 ? $year - 1 : $year, |
415
|
|
|
'month' => $month == 1 ? 12 : $month - 1, |
416
|
|
|
'disabled' => $modSettings['cal_minyear'] > ($month == 1 ? $year - 1 : $year), |
417
|
|
|
), |
418
|
|
|
'next_calendar' => array( |
419
|
|
|
'year' => $month == 12 ? $year + 1 : $year, |
420
|
|
|
'month' => $month == 12 ? 1 : $month + 1, |
421
|
|
|
'disabled' => $modSettings['cal_maxyear'] < ($month == 12 ? $year + 1 : $year), |
422
|
|
|
), |
423
|
|
|
'size' => empty($modSettings['cal_display_type']) ? 'large' : 'small', |
424
|
|
|
); |
425
|
|
|
|
426
|
|
|
// Get today's date. |
427
|
|
|
$today = getTodayInfo(); |
428
|
|
|
|
429
|
|
|
// Get information about this month. |
430
|
|
|
$month_info = array( |
431
|
|
|
'first_day' => array( |
432
|
|
|
'day_of_week' => (int) strftime('%w', mktime(0, 0, 0, $month, 1, $year)), |
433
|
|
|
'week_num' => (int) strftime('%U', mktime(0, 0, 0, $month, 1, $year)), |
434
|
|
|
'date' => strftime('%Y-%m-%d', mktime(0, 0, 0, $month, 1, $year)), |
435
|
|
|
), |
436
|
|
|
'last_day' => array( |
437
|
|
|
'day_of_month' => (int) strftime('%d', mktime(0, 0, 0, $month == 12 ? 1 : $month + 1, 0, $month == 12 ? $year + 1 : $year)), |
438
|
|
|
'date' => strftime('%Y-%m-%d', mktime(0, 0, 0, $month == 12 ? 1 : $month + 1, 0, $month == 12 ? $year + 1 : $year)), |
439
|
|
|
), |
440
|
|
|
'first_day_of_year' => (int) strftime('%w', mktime(0, 0, 0, 1, 1, $year)), |
441
|
|
|
'first_day_of_next_year' => (int) strftime('%w', mktime(0, 0, 0, 1, 1, $year + 1)), |
442
|
|
|
); |
443
|
|
|
|
444
|
|
|
// The number of days the first row is shifted to the right for the starting day. |
445
|
|
|
$nShift = $month_info['first_day']['day_of_week']; |
446
|
|
|
|
447
|
|
|
$calendarOptions['start_day'] = empty($calendarOptions['start_day']) ? 0 : (int) $calendarOptions['start_day']; |
448
|
|
|
|
449
|
|
|
// Starting any day other than Sunday means a shift... |
450
|
|
|
if (!empty($calendarOptions['start_day'])) |
451
|
|
|
{ |
452
|
|
|
$nShift -= $calendarOptions['start_day']; |
453
|
|
|
if ($nShift < 0) |
454
|
|
|
$nShift = 7 + $nShift; |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
// Number of rows required to fit the month. |
458
|
|
|
$nRows = floor(($month_info['last_day']['day_of_month'] + $nShift) / 7); |
459
|
|
|
if (($month_info['last_day']['day_of_month'] + $nShift) % 7) |
460
|
|
|
$nRows++; |
461
|
|
|
|
462
|
|
|
// Fetch the arrays for birthdays, posted events, and holidays. |
463
|
|
|
$bday = $calendarOptions['show_birthdays'] ? getBirthdayRange($month_info['first_day']['date'], $month_info['last_day']['date']) : array(); |
464
|
|
|
$events = $calendarOptions['show_events'] ? getEventRange($month_info['first_day']['date'], $month_info['last_day']['date']) : array(); |
465
|
|
|
$holidays = $calendarOptions['show_holidays'] ? getHolidayRange($month_info['first_day']['date'], $month_info['last_day']['date']) : array(); |
466
|
|
|
|
467
|
|
|
// Days of the week taking into consideration that they may want it to start on any day. |
468
|
|
|
$count = $calendarOptions['start_day']; |
469
|
|
|
for ($i = 0; $i < 7; $i++) |
470
|
|
|
{ |
471
|
|
|
$calendarGrid['week_days'][] = $count; |
472
|
|
|
$count++; |
473
|
|
|
if ($count == 7) |
474
|
|
|
$count = 0; |
475
|
|
|
} |
476
|
|
|
|
477
|
|
|
// Iterate through each week. |
478
|
|
|
$calendarGrid['weeks'] = array(); |
479
|
|
|
for ($nRow = 0; $nRow < $nRows; $nRow++) |
480
|
|
|
{ |
481
|
|
|
// Start off the week - and don't let it go above 52, since that's the number of weeks in a year. |
482
|
|
|
$calendarGrid['weeks'][$nRow] = array( |
483
|
|
|
'days' => array(), |
484
|
|
|
); |
485
|
|
|
|
486
|
|
|
// And figure out all the days. |
487
|
|
|
for ($nCol = 0; $nCol < 7; $nCol++) |
488
|
|
|
{ |
489
|
|
|
$nDay = ($nRow * 7) + $nCol - $nShift + 1; |
490
|
|
|
|
491
|
|
|
if ($nDay < 1 || $nDay > $month_info['last_day']['day_of_month']) |
492
|
|
|
$nDay = 0; |
493
|
|
|
|
494
|
|
|
$date = sprintf('%04d-%02d-%02d', $year, $month, $nDay); |
495
|
|
|
|
496
|
|
|
$calendarGrid['weeks'][$nRow]['days'][$nCol] = array( |
497
|
|
|
'day' => $nDay, |
498
|
|
|
'date' => $date, |
499
|
|
|
'is_today' => $date == $today['date'], |
500
|
|
|
'is_first_day' => !empty($calendarOptions['show_week_num']) && (($month_info['first_day']['day_of_week'] + $nDay - 1) % 7 == $calendarOptions['start_day']), |
501
|
|
|
'is_first_of_month' => $nDay === 1, |
502
|
|
|
'holidays' => !empty($holidays[$date]) ? $holidays[$date] : array(), |
503
|
|
|
'events' => !empty($events[$date]) ? $events[$date] : array(), |
504
|
|
|
'birthdays' => !empty($bday[$date]) ? $bday[$date] : array(), |
505
|
|
|
); |
506
|
|
|
} |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
// What is the last day of the month? |
510
|
|
|
if ($is_previous === true) |
511
|
|
|
$calendarGrid['last_of_month'] = $month_info['last_day']['day_of_month']; |
512
|
|
|
|
513
|
|
|
// We'll use the shift in the template. |
514
|
|
|
$calendarGrid['shift'] = $nShift; |
515
|
|
|
|
516
|
|
|
// Set the previous and the next month's links. |
517
|
|
|
$calendarGrid['previous_calendar']['href'] = $scripturl . '?action=calendar;viewmonth;year=' . $calendarGrid['previous_calendar']['year'] . ';month=' . $calendarGrid['previous_calendar']['month']; |
518
|
|
|
$calendarGrid['next_calendar']['href'] = $scripturl . '?action=calendar;viewmonth;year=' . $calendarGrid['next_calendar']['year'] . ';month=' . $calendarGrid['next_calendar']['month']; |
519
|
|
|
|
520
|
|
|
return $calendarGrid; |
521
|
|
|
} |
522
|
|
|
|
523
|
|
|
/** |
524
|
|
|
* Returns the information needed to show a calendar for the given week. |
525
|
|
|
* @param int $month The month |
526
|
|
|
* @param int $year The year |
527
|
|
|
* @param int $day The day |
528
|
|
|
* @param array $calendarOptions An array of calendar options |
529
|
|
|
* @return array An array of information needed to display the grid for a single week on the calendar |
530
|
|
|
*/ |
531
|
|
|
function getCalendarWeek($month, $year, $day, $calendarOptions) |
532
|
|
|
{ |
533
|
|
|
global $scripturl, $modSettings, $txt; |
534
|
|
|
|
535
|
|
|
// Get today's date. |
536
|
|
|
$today = getTodayInfo(); |
537
|
|
|
|
538
|
|
|
// What is the actual "start date" for the passed day. |
539
|
|
|
$calendarOptions['start_day'] = empty($calendarOptions['start_day']) ? 0 : (int) $calendarOptions['start_day']; |
540
|
|
|
$day_of_week = (int) strftime('%w', mktime(0, 0, 0, $month, $day, $year)); |
541
|
|
|
if ($day_of_week != $calendarOptions['start_day']) |
542
|
|
|
{ |
543
|
|
|
// Here we offset accordingly to get things to the real start of a week. |
544
|
|
|
$date_diff = $day_of_week - $calendarOptions['start_day']; |
545
|
|
|
if ($date_diff < 0) |
546
|
|
|
$date_diff += 7; |
547
|
|
|
$new_timestamp = mktime(0, 0, 0, $month, $day, $year) - $date_diff * 86400; |
548
|
|
|
$day = (int) strftime('%d', $new_timestamp); |
549
|
|
|
$month = (int) strftime('%m', $new_timestamp); |
550
|
|
|
$year = (int) strftime('%Y', $new_timestamp); |
551
|
|
|
} |
552
|
|
|
|
553
|
|
|
// Now start filling in the calendar grid. |
554
|
|
|
$calendarGrid = array( |
555
|
|
|
'show_next_prev' => !empty($calendarOptions['show_next_prev']), |
556
|
|
|
// Previous week is easy - just step back one day. |
557
|
|
|
'previous_week' => array( |
558
|
|
|
'year' => $day == 1 ? ($month == 1 ? $year - 1 : $year) : $year, |
559
|
|
|
'month' => $day == 1 ? ($month == 1 ? 12 : $month - 1) : $month, |
560
|
|
|
'day' => $day == 1 ? 28 : $day - 1, |
561
|
|
|
'disabled' => $day < 7 && $modSettings['cal_minyear'] > ($month == 1 ? $year - 1 : $year), |
562
|
|
|
), |
563
|
|
|
'next_week' => array( |
564
|
|
|
'disabled' => $day > 25 && $modSettings['cal_maxyear'] < ($month == 12 ? $year + 1 : $year), |
565
|
|
|
), |
566
|
|
|
'size' => empty($modSettings['cal_display_type']) ? 'large' : 'small', |
567
|
|
|
); |
568
|
|
|
|
569
|
|
|
// The next week calculation requires a bit more work. |
570
|
|
|
$curTimestamp = mktime(0, 0, 0, $month, $day, $year); |
571
|
|
|
$nextWeekTimestamp = $curTimestamp + 604800; |
572
|
|
|
$calendarGrid['next_week']['day'] = (int) strftime('%d', $nextWeekTimestamp); |
573
|
|
|
$calendarGrid['next_week']['month'] = (int) strftime('%m', $nextWeekTimestamp); |
574
|
|
|
$calendarGrid['next_week']['year'] = (int) strftime('%Y', $nextWeekTimestamp); |
575
|
|
|
|
576
|
|
|
// Fetch the arrays for birthdays, posted events, and holidays. |
577
|
|
|
$startDate = strftime('%Y-%m-%d', $curTimestamp); |
578
|
|
|
$endDate = strftime('%Y-%m-%d', $nextWeekTimestamp); |
579
|
|
|
$bday = $calendarOptions['show_birthdays'] ? getBirthdayRange($startDate, $endDate) : array(); |
580
|
|
|
$events = $calendarOptions['show_events'] ? getEventRange($startDate, $endDate) : array(); |
581
|
|
|
$holidays = $calendarOptions['show_holidays'] ? getHolidayRange($startDate, $endDate) : array(); |
582
|
|
|
|
583
|
|
|
// An adjustment value to apply to all calculated week numbers. |
584
|
|
|
if (!empty($calendarOptions['show_week_num'])) |
585
|
|
|
{ |
586
|
|
|
$timestamp = mktime(0, 0, 0, $month, $day, $year); |
587
|
|
|
$calendarGrid['week_title'] = sprintf($txt['calendar_week_beginning'], date('F', $timestamp), date('j', $timestamp), date('Y', $timestamp)); |
588
|
|
|
} |
589
|
|
|
|
590
|
|
|
// This holds all the main data - there is at least one month! |
591
|
|
|
$calendarGrid['months'] = array(); |
592
|
|
|
$lastDay = 99; |
593
|
|
|
$curDay = $day; |
594
|
|
|
$curDayOfWeek = $calendarOptions['start_day']; |
595
|
|
|
for ($i = 0; $i < 7; $i++) |
596
|
|
|
{ |
597
|
|
|
// Have we gone into a new month (Always happens first cycle too) |
598
|
|
|
if ($lastDay > $curDay) |
599
|
|
|
{ |
600
|
|
|
$curMonth = $lastDay == 99 ? $month : ($month == 12 ? 1 : $month + 1); |
601
|
|
|
$curYear = $lastDay == 99 ? $year : ($curMonth == 1 && $month == 12 ? $year + 1 : $year); |
602
|
|
|
$calendarGrid['months'][$curMonth] = array( |
603
|
|
|
'current_month' => $curMonth, |
604
|
|
|
'current_year' => $curYear, |
605
|
|
|
'days' => array(), |
606
|
|
|
); |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
// Add todays information to the pile! |
610
|
|
|
$date = sprintf('%04d-%02d-%02d', $curYear, $curMonth, $curDay); |
|
|
|
|
611
|
|
|
|
612
|
|
|
$calendarGrid['months'][$curMonth]['days'][$curDay] = array( |
613
|
|
|
'day' => $curDay, |
614
|
|
|
'day_of_week' => $curDayOfWeek, |
615
|
|
|
'date' => $date, |
616
|
|
|
'is_today' => $date == $today['date'], |
617
|
|
|
'holidays' => !empty($holidays[$date]) ? $holidays[$date] : array(), |
618
|
|
|
'events' => !empty($events[$date]) ? $events[$date] : array(), |
619
|
|
|
'birthdays' => !empty($bday[$date]) ? $bday[$date] : array() |
620
|
|
|
); |
621
|
|
|
|
622
|
|
|
// Make the last day what the current day is and work out what the next day is. |
623
|
|
|
$lastDay = $curDay; |
624
|
|
|
$curTimestamp += 86400; |
625
|
|
|
$curDay = (int) strftime('%d', $curTimestamp); |
626
|
|
|
|
627
|
|
|
// Also increment the current day of the week. |
628
|
|
|
$curDayOfWeek = $curDayOfWeek >= 6 ? 0 : ++$curDayOfWeek; |
629
|
|
|
} |
630
|
|
|
|
631
|
|
|
// Set the previous and the next week's links. |
632
|
|
|
$calendarGrid['previous_week']['href'] = $scripturl . '?action=calendar;viewweek;year=' . $calendarGrid['previous_week']['year'] . ';month=' . $calendarGrid['previous_week']['month'] . ';day=' . $calendarGrid['previous_week']['day']; |
633
|
|
|
$calendarGrid['next_week']['href'] = $scripturl . '?action=calendar;viewweek;year=' . $calendarGrid['next_week']['year'] . ';month=' . $calendarGrid['next_week']['month'] . ';day=' . $calendarGrid['next_week']['day']; |
634
|
|
|
|
635
|
|
|
return $calendarGrid; |
636
|
|
|
} |
637
|
|
|
|
638
|
|
|
|
639
|
|
|
/** |
640
|
|
|
* Returns the information needed to show a list of upcoming events, birthdays, and holidays on the calendar. |
641
|
|
|
* @param int $start_date The start of a date range |
642
|
|
|
* @param int $end_date The end of a date range |
643
|
|
|
* @param array $calendarOptions An array of calendar options |
644
|
|
|
* @return array An array of information needed to display a list of upcoming events, etc., on the calendar |
645
|
|
|
*/ |
646
|
|
|
function getCalendarList($start_date, $end_date, $calendarOptions) |
647
|
|
|
{ |
648
|
|
|
global $scripturl, $modSettings, $user_info, $txt, $context, $sourcedir; |
649
|
|
|
require_once($sourcedir . '/Subs.php'); |
650
|
|
|
|
651
|
|
|
// DateTime objects make life easier |
652
|
|
|
$start_object = date_create($start_date); |
653
|
|
|
$end_object = date_create($end_date); |
654
|
|
|
|
655
|
|
|
$calendarGrid = array( |
656
|
|
|
'start_date' => $start_date, |
657
|
|
|
'start_year' => date_format($start_object, 'Y'), |
658
|
|
|
'start_month' => date_format($start_object, 'm'), |
659
|
|
|
'start_day' => date_format($start_object, 'd'), |
660
|
|
|
'end_date' => $end_date, |
661
|
|
|
'end_year' => date_format($end_object, 'Y'), |
662
|
|
|
'end_month' => date_format($end_object, 'm'), |
663
|
|
|
'end_day' => date_format($end_object, 'd'), |
664
|
|
|
); |
665
|
|
|
|
666
|
|
|
$calendarGrid['birthdays'] = $calendarOptions['show_birthdays'] ? getBirthdayRange($start_date, $end_date) : array(); |
667
|
|
|
$calendarGrid['holidays'] = $calendarOptions['show_holidays'] ? getHolidayRange($start_date, $end_date) : array(); |
668
|
|
|
$calendarGrid['events'] = $calendarOptions['show_events'] ? getEventRange($start_date, $end_date) : array(); |
669
|
|
|
|
670
|
|
|
// Get rid of duplicate events |
671
|
|
|
$temp = array(); |
672
|
|
|
foreach ($calendarGrid['events'] as $date => $date_events) |
673
|
|
|
{ |
674
|
|
|
foreach ($date_events as $event_key => $event_val) |
675
|
|
|
{ |
676
|
|
|
if (in_array($event_val['id'], $temp)) |
677
|
|
|
unset($calendarGrid['events'][$date][$event_key]); |
678
|
|
|
else |
679
|
|
|
$temp[] = $event_val['id']; |
680
|
|
|
} |
681
|
|
|
} |
682
|
|
|
|
683
|
|
|
// Give birthdays and holidays a friendly format, without the year |
684
|
|
View Code Duplication |
if (preg_match('~%[AaBbCcDdeGghjmuYy](?:[^%]*%[AaBbCcDdeGghjmuYy])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) |
|
|
|
|
685
|
|
|
$date_format = '%b %d'; |
686
|
|
|
else |
687
|
|
|
$date_format = str_replace(array('%Y', '%y', '%G', '%g', '%C', '%c', '%D'), array('', '', '', '', '', '%b %d', '%m/%d'), $matches[0]); |
688
|
|
|
|
689
|
|
|
foreach (array('birthdays', 'holidays') as $type) |
690
|
|
|
{ |
691
|
|
|
foreach ($calendarGrid[$type] as $date => $date_content) |
692
|
|
|
{ |
693
|
|
|
$date_local = preg_replace('~(?<=\s)0+(\d)~', '$1', trim(timeformat(strtotime($date), $date_format), " \t\n\r\0\x0B,./;:<>()[]{}\\|-_=+")); |
|
|
|
|
694
|
|
|
|
695
|
|
|
$calendarGrid[$type][$date]['date_local'] = $date_local; |
696
|
|
|
} |
697
|
|
|
} |
698
|
|
|
|
699
|
|
|
loadCSSFile('jquery-ui.datepicker.css', array('defer' => false), 'smf_datepicker'); |
700
|
|
|
loadJavaScriptFile('jquery-ui.datepicker.min.js', array('defer' => true), 'smf_datepicker'); |
701
|
|
|
addInlineJavaScript(' |
702
|
|
|
$("#calendar_range .date_input").datepicker({ |
703
|
|
|
dateFormat: "yy-mm-dd", |
704
|
|
|
autoSize: true, |
705
|
|
|
isRTL: ' . ($context['right_to_left'] ? 'true' : 'false') . ', |
706
|
|
|
constrainInput: true, |
707
|
|
|
showAnim: "", |
708
|
|
|
showButtonPanel: false, |
709
|
|
|
minDate: "' . $modSettings['cal_minyear'] . '-01-01", |
710
|
|
|
maxDate: "' . $modSettings['cal_maxyear'] . '-12-31", |
711
|
|
|
yearRange: "' . $modSettings['cal_minyear'] . ':' . $modSettings['cal_maxyear'] . '", |
712
|
|
|
hideIfNoPrevNext: true, |
713
|
|
|
monthNames: ["' . implode('", "', $txt['months_titles']) . '"], |
714
|
|
|
monthNamesShort: ["' . implode('", "', $txt['months_short']) . '"], |
715
|
|
|
dayNames: ["' . implode('", "', $txt['days']) . '"], |
716
|
|
|
dayNamesShort: ["' . implode('", "', $txt['days_short']) . '"], |
717
|
|
|
dayNamesMin: ["' . implode('", "', $txt['days_short']) . '"], |
718
|
|
|
prevText: "' . $txt['prev_month'] . '", |
719
|
|
|
nextText: "' . $txt['next_month'] . '", |
720
|
|
|
}); |
721
|
|
|
var date_entry = document.getElementById("calendar_range"); |
722
|
|
|
', true); |
723
|
|
|
|
724
|
|
|
return $calendarGrid; |
725
|
|
|
} |
726
|
|
|
|
727
|
|
|
/** |
728
|
|
|
* Retrieve all events for the given days, independently of the users offset. |
729
|
|
|
* cache callback function used to retrieve the birthdays, holidays, and events between now and now + days_to_index. |
730
|
|
|
* widens the search range by an extra 24 hours to support time offset shifts. |
731
|
|
|
* used by the cache_getRecentEvents function to get the information needed to calculate the events taking the users time offset into account. |
732
|
|
|
* |
733
|
|
|
* @param int $days_to_index How many days' worth of info to index |
734
|
|
|
* @return array An array containing the data that was cached as well as an expression to calculate whether the data should be refreshed and when it expires |
735
|
|
|
*/ |
736
|
|
|
function cache_getOffsetIndependentEvents($days_to_index) |
737
|
|
|
{ |
738
|
|
|
$low_date = strftime('%Y-%m-%d', forum_time(false) - 24 * 3600); |
739
|
|
|
$high_date = strftime('%Y-%m-%d', forum_time(false) + $days_to_index * 24 * 3600); |
740
|
|
|
|
741
|
|
|
return array( |
742
|
|
|
'data' => array( |
743
|
|
|
'holidays' => getHolidayRange($low_date, $high_date), |
744
|
|
|
'birthdays' => getBirthdayRange($low_date, $high_date), |
745
|
|
|
'events' => getEventRange($low_date, $high_date, false), |
746
|
|
|
), |
747
|
|
|
'refresh_eval' => 'return \'' . strftime('%Y%m%d', forum_time(false)) . '\' != strftime(\'%Y%m%d\', forum_time(false)) || (!empty($modSettings[\'calendar_updated\']) && ' . time() . ' < $modSettings[\'calendar_updated\']);', |
748
|
|
|
'expires' => time() + 3600, |
749
|
|
|
); |
750
|
|
|
} |
751
|
|
|
|
752
|
|
|
/** |
753
|
|
|
* cache callback function used to retrieve the upcoming birthdays, holidays, and events within the given period, taking into account the users time offset. |
754
|
|
|
* Called from the BoardIndex to display the current day's events on the board index |
755
|
|
|
* used by the board index and SSI to show the upcoming events. |
756
|
|
|
* @param array $eventOptions An array of event options. Only 'num_days_shown' is used here |
757
|
|
|
* @return array An array containing the info that was cached as well as a few other relevant things |
758
|
|
|
*/ |
759
|
|
|
function cache_getRecentEvents($eventOptions) |
760
|
|
|
{ |
761
|
|
|
// With the 'static' cached data we can calculate the user-specific data. |
762
|
|
|
$cached_data = cache_quick_get('calendar_index', 'Subs-Calendar.php', 'cache_getOffsetIndependentEvents', array($eventOptions['num_days_shown'])); |
763
|
|
|
|
764
|
|
|
// Get the information about today (from user perspective). |
765
|
|
|
$today = getTodayInfo(); |
766
|
|
|
|
767
|
|
|
$return_data = array( |
768
|
|
|
'calendar_holidays' => array(), |
769
|
|
|
'calendar_birthdays' => array(), |
770
|
|
|
'calendar_events' => array(), |
771
|
|
|
); |
772
|
|
|
|
773
|
|
|
// Set the event span to be shown in seconds. |
774
|
|
|
$days_for_index = $eventOptions['num_days_shown'] * 86400; |
775
|
|
|
|
776
|
|
|
// Get the current member time/date. |
777
|
|
|
$now = forum_time(); |
778
|
|
|
|
779
|
|
|
// Holidays between now and now + days. |
780
|
|
|
for ($i = $now; $i < $now + $days_for_index; $i += 86400) |
781
|
|
|
{ |
782
|
|
|
if (isset($cached_data['holidays'][strftime('%Y-%m-%d', $i)])) |
783
|
|
|
$return_data['calendar_holidays'] = array_merge($return_data['calendar_holidays'], $cached_data['holidays'][strftime('%Y-%m-%d', $i)]); |
784
|
|
|
} |
785
|
|
|
|
786
|
|
|
// Happy Birthday, guys and gals! |
787
|
|
|
for ($i = $now; $i < $now + $days_for_index; $i += 86400) |
788
|
|
|
{ |
789
|
|
|
$loop_date = strftime('%Y-%m-%d', $i); |
790
|
|
|
if (isset($cached_data['birthdays'][$loop_date])) |
791
|
|
|
{ |
792
|
|
|
foreach ($cached_data['birthdays'][$loop_date] as $index => $dummy) |
|
|
|
|
793
|
|
|
$cached_data['birthdays'][strftime('%Y-%m-%d', $i)][$index]['is_today'] = $loop_date === $today['date']; |
794
|
|
|
$return_data['calendar_birthdays'] = array_merge($return_data['calendar_birthdays'], $cached_data['birthdays'][$loop_date]); |
795
|
|
|
} |
796
|
|
|
} |
797
|
|
|
|
798
|
|
|
$duplicates = array(); |
799
|
|
|
for ($i = $now; $i < $now + $days_for_index; $i += 86400) |
800
|
|
|
{ |
801
|
|
|
// Determine the date of the current loop step. |
802
|
|
|
$loop_date = strftime('%Y-%m-%d', $i); |
803
|
|
|
|
804
|
|
|
// No events today? Check the next day. |
805
|
|
|
if (empty($cached_data['events'][$loop_date])) |
806
|
|
|
continue; |
807
|
|
|
|
808
|
|
|
// Loop through all events to add a few last-minute values. |
809
|
|
|
foreach ($cached_data['events'][$loop_date] as $ev => $event) |
|
|
|
|
810
|
|
|
{ |
811
|
|
|
// Create a shortcut variable for easier access. |
812
|
|
|
$this_event = &$cached_data['events'][$loop_date][$ev]; |
813
|
|
|
|
814
|
|
|
// Skip duplicates. |
815
|
|
|
if (isset($duplicates[$this_event['topic'] . $this_event['title']])) |
816
|
|
|
{ |
817
|
|
|
unset($cached_data['events'][$loop_date][$ev]); |
818
|
|
|
continue; |
819
|
|
|
} |
820
|
|
|
else |
821
|
|
|
$duplicates[$this_event['topic'] . $this_event['title']] = true; |
822
|
|
|
|
823
|
|
|
// Might be set to true afterwards, depending on the permissions. |
824
|
|
|
$this_event['can_edit'] = false; |
825
|
|
|
$this_event['is_today'] = $loop_date === $today['date']; |
826
|
|
|
$this_event['date'] = $loop_date; |
827
|
|
|
} |
828
|
|
|
|
829
|
|
|
if (!empty($cached_data['events'][$loop_date])) |
830
|
|
|
$return_data['calendar_events'] = array_merge($return_data['calendar_events'], $cached_data['events'][$loop_date]); |
831
|
|
|
} |
832
|
|
|
|
833
|
|
|
// Mark the last item so that a list separator can be used in the template. |
834
|
|
View Code Duplication |
for ($i = 0, $n = count($return_data['calendar_birthdays']); $i < $n; $i++) |
|
|
|
|
835
|
|
|
$return_data['calendar_birthdays'][$i]['is_last'] = !isset($return_data['calendar_birthdays'][$i + 1]); |
836
|
|
View Code Duplication |
for ($i = 0, $n = count($return_data['calendar_events']); $i < $n; $i++) |
|
|
|
|
837
|
|
|
$return_data['calendar_events'][$i]['is_last'] = !isset($return_data['calendar_events'][$i + 1]); |
838
|
|
|
|
839
|
|
|
return array( |
840
|
|
|
'data' => $return_data, |
841
|
|
|
'expires' => time() + 3600, |
842
|
|
|
'refresh_eval' => 'return \'' . strftime('%Y%m%d', forum_time(false)) . '\' != strftime(\'%Y%m%d\', forum_time(false)) || (!empty($modSettings[\'calendar_updated\']) && ' . time() . ' < $modSettings[\'calendar_updated\']);', |
843
|
|
|
'post_retri_eval' => ' |
844
|
|
|
global $context, $scripturl, $user_info; |
845
|
|
|
|
846
|
|
|
foreach ($cache_block[\'data\'][\'calendar_events\'] as $k => $event) |
847
|
|
|
{ |
848
|
|
|
// Remove events that the user may not see or wants to ignore. |
849
|
|
|
if ((count(array_intersect($user_info[\'groups\'], $event[\'allowed_groups\'])) === 0 && !allowedTo(\'admin_forum\') && !empty($event[\'id_board\'])) || in_array($event[\'id_board\'], $user_info[\'ignoreboards\'])) |
850
|
|
|
unset($cache_block[\'data\'][\'calendar_events\'][$k]); |
851
|
|
|
else |
852
|
|
|
{ |
853
|
|
|
// Whether the event can be edited depends on the permissions. |
854
|
|
|
$cache_block[\'data\'][\'calendar_events\'][$k][\'can_edit\'] = allowedTo(\'calendar_edit_any\') || ($event[\'poster\'] == $user_info[\'id\'] && allowedTo(\'calendar_edit_own\')); |
855
|
|
|
|
856
|
|
|
// The added session code makes this URL not cachable. |
857
|
|
|
$cache_block[\'data\'][\'calendar_events\'][$k][\'modify_href\'] = $scripturl . \'?action=\' . ($event[\'topic\'] == 0 ? \'calendar;sa=post;\' : \'post;msg=\' . $event[\'msg\'] . \';topic=\' . $event[\'topic\'] . \'.0;calendar;\') . \'eventid=\' . $event[\'id\'] . \';\' . $context[\'session_var\'] . \'=\' . $context[\'session_id\']; |
858
|
|
|
} |
859
|
|
|
} |
860
|
|
|
|
861
|
|
|
if (empty($params[0][\'include_holidays\'])) |
862
|
|
|
$cache_block[\'data\'][\'calendar_holidays\'] = array(); |
863
|
|
|
if (empty($params[0][\'include_birthdays\'])) |
864
|
|
|
$cache_block[\'data\'][\'calendar_birthdays\'] = array(); |
865
|
|
|
if (empty($params[0][\'include_events\'])) |
866
|
|
|
$cache_block[\'data\'][\'calendar_events\'] = array(); |
867
|
|
|
|
868
|
|
|
$cache_block[\'data\'][\'show_calendar\'] = !empty($cache_block[\'data\'][\'calendar_holidays\']) || !empty($cache_block[\'data\'][\'calendar_birthdays\']) || !empty($cache_block[\'data\'][\'calendar_events\']);', |
869
|
|
|
); |
870
|
|
|
} |
871
|
|
|
|
872
|
|
|
/** |
873
|
|
|
* Makes sure the calendar post is valid. |
874
|
|
|
*/ |
875
|
|
|
function validateEventPost() |
876
|
|
|
{ |
877
|
|
|
global $modSettings, $smcFunc; |
878
|
|
|
|
879
|
|
|
if (!isset($_POST['deleteevent'])) |
880
|
|
|
{ |
881
|
|
|
// The 2.1 way |
882
|
|
|
if (isset($_POST['start_date'])) |
883
|
|
|
{ |
884
|
|
|
$d = date_parse($_POST['start_date']); |
885
|
|
View Code Duplication |
if (!empty($d['error_count']) || !empty($d['warning_count'])) |
|
|
|
|
886
|
|
|
fatal_lang_error('invalid_date', false); |
887
|
|
|
if (empty($d['year'])) |
888
|
|
|
fatal_lang_error('event_year_missing', false); |
889
|
|
|
if (empty($d['month'])) |
890
|
|
|
fatal_lang_error('event_month_missing', false); |
891
|
|
|
} |
892
|
|
|
elseif (isset($_POST['start_datetime'])) |
893
|
|
|
{ |
894
|
|
|
$d = date_parse($_POST['start_datetime']); |
895
|
|
View Code Duplication |
if (!empty($d['error_count']) || !empty($d['warning_count'])) |
|
|
|
|
896
|
|
|
fatal_lang_error('invalid_date', false); |
897
|
|
|
if (empty($d['year'])) |
898
|
|
|
fatal_lang_error('event_year_missing', false); |
899
|
|
|
if (empty($d['month'])) |
900
|
|
|
fatal_lang_error('event_month_missing', false); |
901
|
|
|
} |
902
|
|
|
// The 2.0 way |
903
|
|
|
else |
904
|
|
|
{ |
905
|
|
|
// No month? No year? |
906
|
|
|
if (!isset($_POST['month'])) |
907
|
|
|
fatal_lang_error('event_month_missing', false); |
908
|
|
|
if (!isset($_POST['year'])) |
909
|
|
|
fatal_lang_error('event_year_missing', false); |
910
|
|
|
|
911
|
|
|
// Check the month and year... |
912
|
|
|
if ($_POST['month'] < 1 || $_POST['month'] > 12) |
913
|
|
|
fatal_lang_error('invalid_month', false); |
914
|
|
View Code Duplication |
if ($_POST['year'] < $modSettings['cal_minyear'] || $_POST['year'] > $modSettings['cal_maxyear']) |
|
|
|
|
915
|
|
|
fatal_lang_error('invalid_year', false); |
916
|
|
|
} |
917
|
|
|
} |
918
|
|
|
|
919
|
|
|
// Make sure they're allowed to post... |
920
|
|
|
isAllowedTo('calendar_post'); |
921
|
|
|
|
922
|
|
|
// If they want to us to calculate an end date, make sure it will fit in an acceptable range. |
923
|
|
|
if (isset($_POST['span'])) |
924
|
|
|
{ |
925
|
|
|
if (($_POST['span'] < 1) || (!empty($modSettings['cal_maxspan']) && $_POST['span'] > $modSettings['cal_maxspan'])) |
926
|
|
|
fatal_lang_error('invalid_days_numb', false); |
927
|
|
|
} |
928
|
|
|
|
929
|
|
|
// There is no need to validate the following values if we are just deleting the event. |
930
|
|
|
if (!isset($_POST['deleteevent'])) |
931
|
|
|
{ |
932
|
|
|
// If we're doing things the 2.0 way, check the day |
933
|
|
|
if (empty($_POST['start_date']) && empty($_POST['start_datetime'])) |
934
|
|
|
{ |
935
|
|
|
// No day? |
936
|
|
|
if (!isset($_POST['day'])) |
937
|
|
|
fatal_lang_error('event_day_missing', false); |
938
|
|
|
|
939
|
|
|
// Bad day? |
940
|
|
|
if (!checkdate($_POST['month'], $_POST['day'], $_POST['year'])) |
941
|
|
|
fatal_lang_error('invalid_date', false); |
942
|
|
|
} |
943
|
|
|
|
944
|
|
|
if (!isset($_POST['evtitle']) && !isset($_POST['subject'])) |
945
|
|
|
fatal_lang_error('event_title_missing', false); |
946
|
|
|
elseif (!isset($_POST['evtitle'])) |
947
|
|
|
$_POST['evtitle'] = $_POST['subject']; |
948
|
|
|
|
949
|
|
|
// No title? |
950
|
|
|
if ($smcFunc['htmltrim']($_POST['evtitle']) === '') |
951
|
|
|
fatal_lang_error('no_event_title', false); |
952
|
|
View Code Duplication |
if ($smcFunc['strlen']($_POST['evtitle']) > 100) |
|
|
|
|
953
|
|
|
$_POST['evtitle'] = $smcFunc['substr']($_POST['evtitle'], 0, 100); |
954
|
|
|
$_POST['evtitle'] = str_replace(';', '', $_POST['evtitle']); |
955
|
|
|
} |
956
|
|
|
} |
957
|
|
|
|
958
|
|
|
/** |
959
|
|
|
* Get the event's poster. |
960
|
|
|
* |
961
|
|
|
* @param int $event_id The ID of the event |
962
|
|
|
* @return int|bool The ID of the poster or false if the event was not found |
963
|
|
|
*/ |
964
|
|
View Code Duplication |
function getEventPoster($event_id) |
|
|
|
|
965
|
|
|
{ |
966
|
|
|
global $smcFunc; |
967
|
|
|
|
968
|
|
|
// A simple database query, how hard can that be? |
969
|
|
|
$request = $smcFunc['db_query']('', ' |
970
|
|
|
SELECT id_member |
971
|
|
|
FROM {db_prefix}calendar |
972
|
|
|
WHERE id_event = {int:id_event} |
973
|
|
|
LIMIT 1', |
974
|
|
|
array( |
975
|
|
|
'id_event' => $event_id, |
976
|
|
|
) |
977
|
|
|
); |
978
|
|
|
|
979
|
|
|
// No results, return false. |
980
|
|
|
if ($smcFunc['db_num_rows'] === 0) |
981
|
|
|
return false; |
982
|
|
|
|
983
|
|
|
// Grab the results and return. |
984
|
|
|
list ($poster) = $smcFunc['db_fetch_row']($request); |
985
|
|
|
$smcFunc['db_free_result']($request); |
986
|
|
|
return (int) $poster; |
987
|
|
|
} |
988
|
|
|
|
989
|
|
|
/** |
990
|
|
|
* Consolidating the various INSERT statements into this function. |
991
|
|
|
* Inserts the passed event information into the calendar table. |
992
|
|
|
* Allows to either set a time span (in days) or an end_date. |
993
|
|
|
* Does not check any permissions of any sort. |
994
|
|
|
* |
995
|
|
|
* @param array $eventOptions An array of event options ('title', 'span', 'start_date', 'end_date', etc.) |
996
|
|
|
*/ |
997
|
|
|
function insertEvent(&$eventOptions) |
998
|
|
|
{ |
999
|
|
|
global $smcFunc, $context; |
1000
|
|
|
|
1001
|
|
|
// Add special chars to the title. |
1002
|
|
|
$eventOptions['title'] = $smcFunc['htmlspecialchars']($eventOptions['title'], ENT_QUOTES); |
1003
|
|
|
|
1004
|
|
|
$eventOptions['location'] = isset($eventOptions['location']) ? $smcFunc['htmlspecialchars']($eventOptions['location'], ENT_QUOTES) : ''; |
1005
|
|
|
|
1006
|
|
|
// Set the start and end dates and times |
1007
|
|
|
list($start_date, $end_date, $start_time, $end_time, $tz) = setEventStartEnd($eventOptions); |
1008
|
|
|
|
1009
|
|
|
// If no topic and board are given, they are not linked to a topic. |
1010
|
|
|
$eventOptions['board'] = isset($eventOptions['board']) ? (int) $eventOptions['board'] : 0; |
1011
|
|
|
$eventOptions['topic'] = isset($eventOptions['topic']) ? (int) $eventOptions['topic'] : 0; |
1012
|
|
|
|
1013
|
|
|
$event_columns = array( |
1014
|
|
|
'id_board' => 'int', 'id_topic' => 'int', 'title' => 'string-60', 'id_member' => 'int', |
1015
|
|
|
'start_date' => 'date', 'end_date' => 'date', 'location' => 'string-255', |
1016
|
|
|
); |
1017
|
|
|
$event_parameters = array( |
1018
|
|
|
$eventOptions['board'], $eventOptions['topic'], $eventOptions['title'], $eventOptions['member'], |
1019
|
|
|
$start_date, $end_date, $eventOptions['location'], |
1020
|
|
|
); |
1021
|
|
View Code Duplication |
if (!empty($start_time) && !empty($end_time) && !empty($tz) && in_array($tz, timezone_identifiers_list(DateTimeZone::ALL_WITH_BC))) |
|
|
|
|
1022
|
|
|
{ |
1023
|
|
|
$event_columns['start_time'] = 'time'; |
1024
|
|
|
$event_parameters[] = $start_time; |
1025
|
|
|
$event_columns['end_time'] = 'time'; |
1026
|
|
|
$event_parameters[] = $end_time; |
1027
|
|
|
$event_columns['timezone'] = 'string'; |
1028
|
|
|
$event_parameters[] = $tz; |
1029
|
|
|
} |
1030
|
|
|
|
1031
|
|
|
call_integration_hook('integrate_create_event', array(&$eventOptions, &$event_columns, &$event_parameters)); |
1032
|
|
|
|
1033
|
|
|
// Insert the event! |
1034
|
|
|
$eventOptions['id'] = $smcFunc['db_insert']('', |
1035
|
|
|
'{db_prefix}calendar', |
1036
|
|
|
$event_columns, |
1037
|
|
|
$event_parameters, |
1038
|
|
|
array('id_event'), |
1039
|
|
|
1 |
1040
|
|
|
); |
1041
|
|
|
|
1042
|
|
|
// If this isn't tied to a topic, we need to notify people about it. |
1043
|
|
|
if (empty($eventOptions['topic'])) |
1044
|
|
|
{ |
1045
|
|
|
$smcFunc['db_insert']('insert', |
1046
|
|
|
'{db_prefix}background_tasks', |
1047
|
|
|
array('task_file' => 'string', 'task_class' => 'string', 'task_data' => 'string', 'claimed_time' => 'int'), |
1048
|
|
|
array('$sourcedir/tasks/EventNew-Notify.php', 'EventNew_Notify_Background', json_encode(array( |
1049
|
|
|
'event_title' => $eventOptions['title'], |
1050
|
|
|
'event_id' => $eventOptions['id'], |
1051
|
|
|
'sender_id' => $eventOptions['member'], |
1052
|
|
|
'sender_name' => $eventOptions['member'] == $context['user']['id'] ? $context['user']['name'] : '', |
1053
|
|
|
'time' => time(), |
1054
|
|
|
)), 0), |
1055
|
|
|
array('id_task') |
1056
|
|
|
); |
1057
|
|
|
} |
1058
|
|
|
|
1059
|
|
|
// Update the settings to show something calendar-ish was updated. |
1060
|
|
|
updateSettings(array( |
1061
|
|
|
'calendar_updated' => time(), |
1062
|
|
|
)); |
1063
|
|
|
} |
1064
|
|
|
|
1065
|
|
|
/** |
1066
|
|
|
* modifies an event. |
1067
|
|
|
* allows to either set a time span (in days) or an end_date. |
1068
|
|
|
* does not check any permissions of any sort. |
1069
|
|
|
* |
1070
|
|
|
* @param int $event_id The ID of the event |
1071
|
|
|
* @param array $eventOptions An array of event information |
1072
|
|
|
*/ |
1073
|
|
|
function modifyEvent($event_id, &$eventOptions) |
1074
|
|
|
{ |
1075
|
|
|
global $smcFunc; |
1076
|
|
|
|
1077
|
|
|
// Properly sanitize the title and location |
1078
|
|
|
$eventOptions['title'] = $smcFunc['htmlspecialchars']($eventOptions['title'], ENT_QUOTES); |
1079
|
|
|
$eventOptions['location'] = $smcFunc['htmlspecialchars']($eventOptions['location'], ENT_QUOTES); |
1080
|
|
|
|
1081
|
|
|
// Set the new start and end dates and times |
1082
|
|
|
list($start_date, $end_date, $start_time, $end_time, $tz) = setEventStartEnd($eventOptions); |
1083
|
|
|
|
1084
|
|
|
$event_columns = array( |
1085
|
|
|
'start_date' => '{date:start_date}', |
1086
|
|
|
'end_date' => '{date:end_date}', |
1087
|
|
|
'title' => 'SUBSTRING({string:title}, 1, 60)', |
1088
|
|
|
'id_board' => '{int:id_board}', |
1089
|
|
|
'id_topic' => '{int:id_topic}', |
1090
|
|
|
'location' => 'SUBSTRING({string:location}, 1, 255)', |
1091
|
|
|
); |
1092
|
|
|
$event_parameters = array( |
1093
|
|
|
'start_date' => $start_date, |
1094
|
|
|
'end_date' => $end_date, |
1095
|
|
|
'title' => $eventOptions['title'], |
1096
|
|
|
'location' => $eventOptions['location'], |
1097
|
|
|
'id_board' => isset($eventOptions['board']) ? (int) $eventOptions['board'] : 0, |
1098
|
|
|
'id_topic' => isset($eventOptions['topic']) ? (int) $eventOptions['topic'] : 0, |
1099
|
|
|
); |
1100
|
|
View Code Duplication |
if (!empty($start_time) && !empty($end_time) && !empty($tz) && in_array($tz, timezone_identifiers_list(DateTimeZone::ALL_WITH_BC))) |
|
|
|
|
1101
|
|
|
{ |
1102
|
|
|
$event_columns['start_time'] = '{time:start_time}'; |
1103
|
|
|
$event_parameters['start_time'] = $start_time; |
1104
|
|
|
$event_columns['end_time'] = '{time:end_time}'; |
1105
|
|
|
$event_parameters['end_time'] = $end_time; |
1106
|
|
|
$event_columns['timezone'] = '{string:timezone}'; |
1107
|
|
|
$event_parameters['timezone'] = $tz; |
1108
|
|
|
} |
1109
|
|
|
|
1110
|
|
|
// This is to prevent hooks to modify the id of the event |
1111
|
|
|
$real_event_id = $event_id; |
1112
|
|
|
call_integration_hook('integrate_modify_event', array($event_id, &$eventOptions, &$event_columns, &$event_parameters)); |
1113
|
|
|
|
1114
|
|
|
$column_clauses = array(); |
1115
|
|
|
foreach ($event_columns as $col => $crit) |
1116
|
|
|
$column_clauses[] = $col . ' = ' . $crit; |
1117
|
|
|
|
1118
|
|
|
$smcFunc['db_query']('', ' |
1119
|
|
|
UPDATE {db_prefix}calendar |
1120
|
|
|
SET |
1121
|
|
|
' . implode(', ', $column_clauses) . ' |
1122
|
|
|
WHERE id_event = {int:id_event}', |
1123
|
|
|
array_merge( |
1124
|
|
|
$event_parameters, |
1125
|
|
|
array( |
1126
|
|
|
'id_event' => $real_event_id |
1127
|
|
|
) |
1128
|
|
|
) |
1129
|
|
|
); |
1130
|
|
|
|
1131
|
|
|
if (empty($start_time) || empty($end_time) || empty($tz) || !in_array($tz, timezone_identifiers_list(DateTimeZone::ALL_WITH_BC))) |
1132
|
|
|
{ |
1133
|
|
|
$smcFunc['db_query']('', ' |
1134
|
|
|
UPDATE {db_prefix}calendar |
1135
|
|
|
SET start_time = NULL, end_time = NULL, timezone = NULL |
1136
|
|
|
WHERE id_event = {int:id_event}', |
1137
|
|
|
array( |
1138
|
|
|
'id_event' => $real_event_id |
1139
|
|
|
) |
1140
|
|
|
); |
1141
|
|
|
} |
1142
|
|
|
|
1143
|
|
|
updateSettings(array( |
1144
|
|
|
'calendar_updated' => time(), |
1145
|
|
|
)); |
1146
|
|
|
} |
1147
|
|
|
|
1148
|
|
|
/** |
1149
|
|
|
* Remove an event |
1150
|
|
|
* removes an event. |
1151
|
|
|
* does no permission checks. |
1152
|
|
|
* |
1153
|
|
|
* @param int $event_id The ID of the event to remove |
1154
|
|
|
*/ |
1155
|
|
|
function removeEvent($event_id) |
1156
|
|
|
{ |
1157
|
|
|
global $smcFunc; |
1158
|
|
|
|
1159
|
|
|
$smcFunc['db_query']('', ' |
1160
|
|
|
DELETE FROM {db_prefix}calendar |
1161
|
|
|
WHERE id_event = {int:id_event}', |
1162
|
|
|
array( |
1163
|
|
|
'id_event' => $event_id, |
1164
|
|
|
) |
1165
|
|
|
); |
1166
|
|
|
|
1167
|
|
|
call_integration_hook('integrate_remove_event', array($event_id)); |
1168
|
|
|
|
1169
|
|
|
updateSettings(array( |
1170
|
|
|
'calendar_updated' => time(), |
1171
|
|
|
)); |
1172
|
|
|
} |
1173
|
|
|
|
1174
|
|
|
/** |
1175
|
|
|
* Gets all the events properties |
1176
|
|
|
* |
1177
|
|
|
* @param int $event_id The ID of the event |
1178
|
|
|
* @return array An array of event information |
1179
|
|
|
*/ |
1180
|
|
|
function getEventProperties($event_id) |
1181
|
|
|
{ |
1182
|
|
|
global $smcFunc; |
1183
|
|
|
|
1184
|
|
|
$request = $smcFunc['db_query']('', ' |
1185
|
|
|
SELECT |
1186
|
|
|
c.id_event, c.id_board, c.id_topic, c.id_member, c.title, |
1187
|
|
|
c.start_date, c.end_date, c.start_time, c.end_time, c.timezone, c.location, |
1188
|
|
|
t.id_first_msg, t.id_member_started, |
1189
|
|
|
mb.real_name, m.modified_time |
1190
|
|
|
FROM {db_prefix}calendar AS c |
1191
|
|
|
LEFT JOIN {db_prefix}topics AS t ON (t.id_topic = c.id_topic) |
1192
|
|
|
LEFT JOIN {db_prefix}members AS mb ON (mb.id_member = t.id_member_started) |
1193
|
|
|
LEFT JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) |
1194
|
|
|
WHERE c.id_event = {int:id_event}', |
1195
|
|
|
array( |
1196
|
|
|
'id_event' => $event_id, |
1197
|
|
|
) |
1198
|
|
|
); |
1199
|
|
|
|
1200
|
|
|
// If nothing returned, we are in poo, poo. |
1201
|
|
|
if ($smcFunc['db_num_rows']($request) === 0) |
1202
|
|
|
return false; |
1203
|
|
|
|
1204
|
|
|
$row = $smcFunc['db_fetch_assoc']($request); |
1205
|
|
|
$smcFunc['db_free_result']($request); |
1206
|
|
|
|
1207
|
|
|
list($start, $end, $allday, $span, $tz, $tz_abbrev) = buildEventDatetimes($row); |
1208
|
|
|
|
1209
|
|
|
// Sanity check |
1210
|
|
View Code Duplication |
if (!empty($start['error_count']) || !empty($start['warning_count']) || !empty($end['error_count']) || !empty($end['warning_count'])) |
|
|
|
|
1211
|
|
|
return false; |
1212
|
|
|
|
1213
|
|
|
$return_value = array( |
1214
|
|
|
'boards' => array(), |
1215
|
|
|
'board' => $row['id_board'], |
1216
|
|
|
'new' => 0, |
1217
|
|
|
'eventid' => $event_id, |
1218
|
|
|
'year' => $start['year'], |
1219
|
|
|
'month' => $start['month'], |
1220
|
|
|
'day' => $start['day'], |
1221
|
|
|
'hour' => !$allday ? $start['hour'] : null, |
1222
|
|
|
'minute' => !$allday ? $start['minute'] : null, |
1223
|
|
|
'second' => !$allday ? $start['second'] : null, |
1224
|
|
|
'start_date' => $row['start_date'], |
1225
|
|
|
'start_date_local' => $start['date_local'], |
1226
|
|
|
'start_date_orig' => $start['date_orig'], |
1227
|
|
|
'start_time' => !$allday ? $row['start_time'] : null, |
1228
|
|
|
'start_time_local' => !$allday ? $start['time_local'] : null, |
1229
|
|
|
'start_time_orig' => !$allday ? $start['time_orig'] : null, |
1230
|
|
|
'start_timestamp' => $start['timestamp'], |
1231
|
|
|
'start_datetime' => $start['datetime'], |
1232
|
|
|
'start_iso_gmdate' => $start['iso_gmdate'], |
1233
|
|
|
'end_year' => $end['year'], |
1234
|
|
|
'end_month' => $end['month'], |
1235
|
|
|
'end_day' => $end['day'], |
1236
|
|
|
'end_hour' => !$allday ? $end['hour'] : null, |
1237
|
|
|
'end_minute' => !$allday ? $end['minute'] : null, |
1238
|
|
|
'end_second' => !$allday ? $end['second'] : null, |
1239
|
|
|
'end_date' => $row['end_date'], |
1240
|
|
|
'end_date_local' => $end['date_local'], |
1241
|
|
|
'end_date_orig' => $end['date_orig'], |
1242
|
|
|
'end_time' => !$allday ? $row['end_time'] : null, |
1243
|
|
|
'end_time_local' => !$allday ? $end['time_local'] : null, |
1244
|
|
|
'end_time_orig' => !$allday ? $end['time_orig'] : null, |
1245
|
|
|
'end_timestamp' => $end['timestamp'], |
1246
|
|
|
'end_datetime' => $end['datetime'], |
1247
|
|
|
'end_iso_gmdate' => $end['iso_gmdate'], |
1248
|
|
|
'allday' => $allday, |
1249
|
|
|
'tz' => !$allday ? $tz : null, |
1250
|
|
|
'tz_abbrev' => !$allday ? $tz_abbrev : null, |
1251
|
|
|
'span' => $span, |
1252
|
|
|
'title' => $row['title'], |
1253
|
|
|
'location' => $row['location'], |
1254
|
|
|
'member' => $row['id_member'], |
1255
|
|
|
'realname' => $row['real_name'], |
1256
|
|
|
'sequence' => $row['modified_time'], |
1257
|
|
|
'topic' => array( |
1258
|
|
|
'id' => $row['id_topic'], |
1259
|
|
|
'member_started' => $row['id_member_started'], |
1260
|
|
|
'first_msg' => $row['id_first_msg'], |
1261
|
|
|
), |
1262
|
|
|
); |
1263
|
|
|
|
1264
|
|
|
$return_value['last_day'] = (int) strftime('%d', mktime(0, 0, 0, $return_value['month'] == 12 ? 1 : $return_value['month'] + 1, 0, $return_value['month'] == 12 ? $return_value['year'] + 1 : $return_value['year'])); |
1265
|
|
|
|
1266
|
|
|
return $return_value; |
1267
|
|
|
} |
1268
|
|
|
|
1269
|
|
|
/** |
1270
|
|
|
* Gets an initial set of date and time values for creating a new event. |
1271
|
|
|
* |
1272
|
|
|
* @return array An array containing an initial set of date and time values for an event. |
1273
|
|
|
*/ |
1274
|
|
|
function getNewEventDatetimes() |
1275
|
|
|
{ |
1276
|
|
|
// Ensure setEventStartEnd() has something to work with |
1277
|
|
|
$now = date_create(); |
1278
|
|
|
$_POST['year'] = !empty($_POST['year']) ? $_POST['year'] : date_format($now, 'Y'); |
1279
|
|
|
$_POST['month'] = !empty($_POST['month']) ? $_POST['month'] : date_format($now, 'm'); |
1280
|
|
|
$_POST['day'] = !empty($_POST['day']) ? $_POST['day'] : date_format($now, 'd'); |
1281
|
|
|
$_POST['hour'] = !empty($_POST['hour']) ? $_POST['hour'] : date_format($now, 'H'); |
1282
|
|
|
$_POST['minute'] = !empty($_POST['minute']) ? $_POST['minute'] : date_format($now, 'i'); |
1283
|
|
|
$_POST['second'] = !empty($_POST['second']) ? $_POST['second'] : date_format($now, 's'); |
1284
|
|
|
|
1285
|
|
|
// Set the basic values for the new event |
1286
|
|
|
$row_keys = array('start_date', 'end_date', 'start_time', 'end_time', 'timezone'); |
1287
|
|
|
$row = array_combine($row_keys, setEventStartEnd()); |
1288
|
|
|
|
1289
|
|
|
// And now set the full suite of values |
1290
|
|
|
list($start, $end, $allday, $span, $tz, $tz_abbrev) = buildEventDatetimes($row); |
1291
|
|
|
|
1292
|
|
|
// Default theme only uses some of this info, but others might want it all |
1293
|
|
|
$eventProperties = array( |
1294
|
|
|
'year' => $start['year'], |
1295
|
|
|
'month' => $start['month'], |
1296
|
|
|
'day' => $start['day'], |
1297
|
|
|
'hour' => !$allday ? $start['hour'] : null, |
1298
|
|
|
'minute' => !$allday ? $start['minute'] : null, |
1299
|
|
|
'second' => !$allday ? $start['second'] : null, |
1300
|
|
|
'start_date' => $row['start_date'], |
1301
|
|
|
'start_date_local' => $start['date_local'], |
1302
|
|
|
'start_date_orig' => $start['date_orig'], |
1303
|
|
|
'start_time' => !$allday ? $row['start_time'] : null, |
1304
|
|
|
'start_time_local' => !$allday ? $start['time_local'] : null, |
1305
|
|
|
'start_time_orig' => !$allday ? $start['time_orig'] : null, |
1306
|
|
|
'start_timestamp' => $start['timestamp'], |
1307
|
|
|
'start_datetime' => $start['datetime'], |
1308
|
|
|
'start_iso_gmdate' => $start['iso_gmdate'], |
1309
|
|
|
'end_year' => $end['year'], |
1310
|
|
|
'end_month' => $end['month'], |
1311
|
|
|
'end_day' => $end['day'], |
1312
|
|
|
'end_hour' => !$allday ? $end['hour'] : null, |
1313
|
|
|
'end_minute' => !$allday ? $end['minute'] : null, |
1314
|
|
|
'end_second' => !$allday ? $end['second'] : null, |
1315
|
|
|
'end_date' => $row['end_date'], |
1316
|
|
|
'end_date_local' => $end['date_local'], |
1317
|
|
|
'end_date_orig' => $end['date_orig'], |
1318
|
|
|
'end_time' => !$allday ? $row['end_time'] : null, |
1319
|
|
|
'end_time_local' => !$allday ? $end['time_local'] : null, |
1320
|
|
|
'end_time_orig' => !$allday ? $end['time_orig'] : null, |
1321
|
|
|
'end_timestamp' => $end['timestamp'], |
1322
|
|
|
'end_datetime' => $end['datetime'], |
1323
|
|
|
'end_iso_gmdate' => $end['iso_gmdate'], |
1324
|
|
|
'allday' => $allday, |
1325
|
|
|
'tz' => !$allday ? $tz : null, |
1326
|
|
|
'tz_abbrev' => !$allday ? $tz_abbrev : null, |
1327
|
|
|
'span' => $span, |
1328
|
|
|
); |
1329
|
|
|
|
1330
|
|
|
return $eventProperties; |
1331
|
|
|
} |
1332
|
|
|
|
1333
|
|
|
/** |
1334
|
|
|
* Set the start and end dates and times for a posted event for insertion into the database. |
1335
|
|
|
* Validates all date and times given to it. |
1336
|
|
|
* Makes sure events do not exceed the maximum allowed duration (if any). |
1337
|
|
|
* If passed an array that defines any time or date parameters, they will be used. Otherwise, gets the values from $_POST. |
1338
|
|
|
* |
1339
|
|
|
* @param array $eventOptions An array of optional time and date parameters (span, start_year, end_month, etc., etc.) |
1340
|
|
|
* @return array An array containing $start_date, $end_date, $start_time, $end_time |
1341
|
|
|
*/ |
1342
|
|
|
function setEventStartEnd($eventOptions = array()) |
1343
|
|
|
{ |
1344
|
|
|
global $modSettings, $user_info; |
1345
|
|
|
|
1346
|
|
|
// Set $span, in case we need it |
1347
|
|
|
$span = isset($eventOptions['span']) ? $eventOptions['span'] : (isset($_POST['span']) ? $_POST['span'] : 0); |
1348
|
|
|
if ($span > 0) |
1349
|
|
|
$span = !empty($modSettings['cal_maxspan']) ? min($modSettings['cal_maxspan'], $span - 1) : $span - 1; |
1350
|
|
|
|
1351
|
|
|
// Define the timezone for this event, falling back to the default if not provided |
1352
|
|
|
if (!empty($eventOptions['tz']) && in_array($eventOptions['tz'], timezone_identifiers_list(DateTimeZone::ALL_WITH_BC))) |
1353
|
|
|
$tz = $eventOptions['tz']; |
1354
|
|
View Code Duplication |
elseif (!empty($_POST['tz']) && in_array($_POST['tz'], timezone_identifiers_list(DateTimeZone::ALL_WITH_BC))) |
|
|
|
|
1355
|
|
|
$tz = $_POST['tz']; |
1356
|
|
|
else |
1357
|
|
|
$tz = getUserTimezone(); |
1358
|
|
|
|
1359
|
|
|
// Is this supposed to be an all day event, or should it have specific start and end times? |
1360
|
|
|
if (isset($eventOptions['allday'])) |
1361
|
|
|
$allday = $eventOptions['allday']; |
1362
|
|
|
elseif (empty($_POST['allday'])) |
1363
|
|
|
$allday = false; |
1364
|
|
|
else |
1365
|
|
|
$allday = true; |
1366
|
|
|
|
1367
|
|
|
// Input might come as individual parameters... |
1368
|
|
|
$start_year = isset($eventOptions['year']) ? $eventOptions['year'] : (isset($_POST['year']) ? $_POST['year'] : null); |
1369
|
|
|
$start_month = isset($eventOptions['month']) ? $eventOptions['month'] : (isset($_POST['month']) ? $_POST['month'] : null); |
1370
|
|
|
$start_day = isset($eventOptions['day']) ? $eventOptions['day'] : (isset($_POST['day']) ? $_POST['day'] : null); |
1371
|
|
|
$start_hour = isset($eventOptions['hour']) ? $eventOptions['hour'] : (isset($_POST['hour']) ? $_POST['hour'] : null); |
1372
|
|
|
$start_minute = isset($eventOptions['minute']) ? $eventOptions['minute'] : (isset($_POST['minute']) ? $_POST['minute'] : null); |
1373
|
|
|
$start_second = isset($eventOptions['second']) ? $eventOptions['second'] : (isset($_POST['second']) ? $_POST['second'] : null); |
1374
|
|
|
$end_year = isset($eventOptions['end_year']) ? $eventOptions['end_year'] : (isset($_POST['end_year']) ? $_POST['end_year'] : null); |
1375
|
|
|
$end_month = isset($eventOptions['end_month']) ? $eventOptions['end_month'] : (isset($_POST['end_month']) ? $_POST['end_month'] : null); |
1376
|
|
|
$end_day = isset($eventOptions['end_day']) ? $eventOptions['end_day'] : (isset($_POST['end_day']) ? $_POST['end_day'] : null); |
1377
|
|
|
$end_hour = isset($eventOptions['end_hour']) ? $eventOptions['end_hour'] : (isset($_POST['end_hour']) ? $_POST['end_hour'] : null); |
1378
|
|
|
$end_minute = isset($eventOptions['end_minute']) ? $eventOptions['end_minute'] : (isset($_POST['end_minute']) ? $_POST['end_minute'] : null); |
1379
|
|
|
$end_second = isset($eventOptions['end_second']) ? $eventOptions['end_second'] : (isset($_POST['end_second']) ? $_POST['end_second'] : null); |
1380
|
|
|
|
1381
|
|
|
// ... or as datetime strings ... |
1382
|
|
|
$start_string = isset($eventOptions['start_datetime']) ? $eventOptions['start_datetime'] : (isset($_POST['start_datetime']) ? $_POST['start_datetime'] : null); |
1383
|
|
|
$end_string = isset($eventOptions['end_datetime']) ? $eventOptions['end_datetime'] : (isset($_POST['end_datetime']) ? $_POST['end_datetime'] : null); |
1384
|
|
|
|
1385
|
|
|
// ... or as date strings and time strings. |
1386
|
|
|
$start_date_string = isset($eventOptions['start_date']) ? $eventOptions['start_date'] : (isset($_POST['start_date']) ? $_POST['start_date'] : null); |
1387
|
|
|
$start_time_string = isset($eventOptions['start_time']) ? $eventOptions['start_time'] : (isset($_POST['start_time']) ? $_POST['start_time'] : null); |
1388
|
|
|
$end_date_string = isset($eventOptions['end_date']) ? $eventOptions['end_date'] : (isset($_POST['end_date']) ? $_POST['end_date'] : null); |
1389
|
|
|
$end_time_string = isset($eventOptions['end_time']) ? $eventOptions['end_time'] : (isset($_POST['end_time']) ? $_POST['end_time'] : null); |
1390
|
|
|
|
1391
|
|
|
// If the date and time were given in separate strings, combine them |
1392
|
|
|
if (empty($start_string) && isset($start_date_string)) |
1393
|
|
|
$start_string = $start_date_string . (isset($start_time_string) ? ' ' . $start_time_string : ''); |
1394
|
|
|
if (empty($end_string) && isset($end_date_string)) |
1395
|
|
|
$end_string = $end_date_string . (isset($end_time_string) ? ' ' . $end_time_string : ''); |
1396
|
|
|
|
1397
|
|
|
// If some form of string input was given, override individually defined options with it |
1398
|
|
View Code Duplication |
if (isset($start_string)) |
|
|
|
|
1399
|
|
|
{ |
1400
|
|
|
$start_string_parsed = date_parse($start_string); |
1401
|
|
|
if (empty($start_string_parsed['error_count']) && empty($start_string_parsed['warning_count'])) |
1402
|
|
|
{ |
1403
|
|
|
if ($start_string_parsed['year'] != false) |
1404
|
|
|
{ |
1405
|
|
|
$start_year = $start_string_parsed['year']; |
1406
|
|
|
$start_month = $start_string_parsed['month']; |
1407
|
|
|
$start_day = $start_string_parsed['day']; |
1408
|
|
|
} |
1409
|
|
|
if ($start_string_parsed['hour'] != false) |
1410
|
|
|
{ |
1411
|
|
|
$start_hour = $start_string_parsed['hour']; |
1412
|
|
|
$start_minute = $start_string_parsed['minute']; |
1413
|
|
|
$start_second = $start_string_parsed['second']; |
1414
|
|
|
} |
1415
|
|
|
} |
1416
|
|
|
} |
1417
|
|
View Code Duplication |
if (isset($end_string)) |
|
|
|
|
1418
|
|
|
{ |
1419
|
|
|
$end_string_parsed = date_parse($end_string); |
1420
|
|
|
if (empty($end_string_parsed['error_count']) && empty($end_string_parsed['warning_count'])) |
1421
|
|
|
{ |
1422
|
|
|
if ($end_string_parsed['year'] != false) |
1423
|
|
|
{ |
1424
|
|
|
$end_year = $end_string_parsed['year']; |
1425
|
|
|
$end_month = $end_string_parsed['month']; |
1426
|
|
|
$end_day = $end_string_parsed['day']; |
1427
|
|
|
} |
1428
|
|
|
if ($end_string_parsed['hour'] != false) |
1429
|
|
|
{ |
1430
|
|
|
$end_hour = $end_string_parsed['hour']; |
1431
|
|
|
$end_minute = $end_string_parsed['minute']; |
1432
|
|
|
$end_second = $end_string_parsed['second']; |
1433
|
|
|
} |
1434
|
|
|
} |
1435
|
|
|
} |
1436
|
|
|
|
1437
|
|
|
// Validate input |
1438
|
|
|
$start_date_isvalid = checkdate($start_month, $start_day, $start_year); |
1439
|
|
|
$end_date_isvalid = checkdate($end_month, $end_day, $end_year); |
1440
|
|
|
|
1441
|
|
|
$start_time_isset = (isset($start_hour) && isset($start_minute) && isset($start_second)); |
1442
|
|
|
$d = date_parse(sprintf('%02d:%02d:%02d', $start_hour, $start_minute, $start_second)); |
1443
|
|
|
$start_time_isvalid = ($d['error_count'] == 0 && $d['warning_count'] == 0) ? true : false; |
1444
|
|
|
|
1445
|
|
|
$end_time_isset = (isset($end_hour) && isset($end_minute) && isset($end_second)); |
1446
|
|
|
$d = date_parse(sprintf('%02d:%02d:%02d', $end_hour, $end_minute, $end_second)); |
1447
|
|
|
$end_time_isvalid = ($d['error_count'] == 0 && $d['warning_count'] == 0) ? true : false; |
1448
|
|
|
|
1449
|
|
|
// Uh-oh... |
1450
|
|
|
if ($start_date_isvalid === false) |
1451
|
|
|
{ |
1452
|
|
|
fatal_lang_error('invalid_date', false); |
1453
|
|
|
} |
1454
|
|
|
|
1455
|
|
|
// Make sure we use valid values for everything |
1456
|
|
|
if ($end_date_isvalid === false) |
1457
|
|
|
{ |
1458
|
|
|
$end_year = $start_year; |
1459
|
|
|
$end_month = $start_month; |
1460
|
|
|
$end_day = $start_day; |
1461
|
|
|
} |
1462
|
|
|
|
1463
|
|
|
if ($allday === true || $start_time_isset === false || $start_time_isvalid === false) |
1464
|
|
|
{ |
1465
|
|
|
$allday = true; |
1466
|
|
|
$start_hour = 0; |
1467
|
|
|
$start_minute = 0; |
1468
|
|
|
$start_second = 0; |
1469
|
|
|
} |
1470
|
|
|
|
1471
|
|
|
if ($allday === true || $end_time_isvalid === false || $end_time_isset === false) |
1472
|
|
|
{ |
1473
|
|
|
$end_hour = $start_hour; |
1474
|
|
|
$end_minute = $start_minute; |
1475
|
|
|
$end_second = $start_second; |
1476
|
|
|
} |
1477
|
|
|
|
1478
|
|
|
// Now create our datetime objects |
1479
|
|
|
$start_object = date_create(sprintf('%04d-%02d-%02d %02d:%02d:%02d', $start_year, $start_month, $start_day, $start_hour, $start_minute, $start_second) . ' ' . $tz); |
1480
|
|
|
$end_object = date_create(sprintf('%04d-%02d-%02d %02d:%02d:%02d', $end_year, $end_month, $end_day, $end_hour, $end_minute, $end_second) . ' ' . $tz); |
1481
|
|
|
|
1482
|
|
|
// Is $end_object too early? |
1483
|
|
|
if ($start_object >= $end_object) |
1484
|
|
|
{ |
1485
|
|
|
$end_object = date_create(sprintf('%04d-%02d-%02d %02d:%02d:%02d', $start_year, $start_month, $start_day, $start_hour, $start_minute, $start_second) . ' ' . $tz); |
1486
|
|
|
if ($span > 0) |
1487
|
|
|
date_add($end_object, date_interval_create_from_date_string($span . ' days')); |
1488
|
|
|
else |
1489
|
|
|
date_add($end_object, date_interval_create_from_date_string('1 hour')); |
1490
|
|
|
} |
1491
|
|
|
|
1492
|
|
|
// Is $end_object too late? |
1493
|
|
|
if (!empty($modSettings['cal_maxspan'])) |
1494
|
|
|
{ |
1495
|
|
|
$date_diff = date_diff($start_object, $end_object); |
1496
|
|
|
if ($date_diff->days > $modSettings['cal_maxspan']) |
1497
|
|
|
{ |
1498
|
|
|
if ($modSettings['cal_maxspan'] > 1) |
1499
|
|
|
{ |
1500
|
|
|
$end_object = date_create(sprintf('%04d-%02d-%02d %02d:%02d:%02d', $start_year, $start_month, $start_day, $start_hour, $start_minute, $start_second) . ' ' . $tz); |
1501
|
|
|
date_add($end_object, date_interval_create_from_date_string($modSettings['cal_maxspan'] . ' days')); |
1502
|
|
|
} |
1503
|
|
|
else |
1504
|
|
|
$end_object = date_create(sprintf('%04d-%02d-%02d %02d:%02d:%02d', $start_year, $start_month, $start_day, '11', '59', '59') . ' ' . $tz); |
1505
|
|
|
} |
1506
|
|
|
} |
1507
|
|
|
|
1508
|
|
|
// Finally, make our strings |
1509
|
|
|
$start_date = date_format($start_object, 'Y-m-d'); |
1510
|
|
|
$end_date = date_format($end_object, 'Y-m-d'); |
1511
|
|
|
|
1512
|
|
|
if ($allday == true) |
1513
|
|
|
{ |
1514
|
|
|
$start_time = null; |
1515
|
|
|
$end_time = null; |
1516
|
|
|
$tz = null; |
1517
|
|
|
} |
1518
|
|
|
else |
1519
|
|
|
{ |
1520
|
|
|
$start_time = date_format($start_object, 'H:i:s'); |
1521
|
|
|
$end_time = date_format($end_object, 'H:i:s'); |
1522
|
|
|
} |
1523
|
|
|
|
1524
|
|
|
return array($start_date, $end_date, $start_time, $end_time, $tz); |
1525
|
|
|
} |
1526
|
|
|
|
1527
|
|
|
/** |
1528
|
|
|
* Helper function for getEventRange, getEventProperties, getNewEventDatetimes, etc. |
1529
|
|
|
* |
1530
|
|
|
* @param array $row A database row representing an event from the calendar table |
1531
|
|
|
* @return array An array containing the start and end date and time properties for the event |
1532
|
|
|
*/ |
1533
|
|
|
function buildEventDatetimes($row) |
1534
|
|
|
{ |
1535
|
|
|
global $sourcedir, $user_info; |
1536
|
|
|
require_once($sourcedir . '/Subs.php'); |
1537
|
|
|
|
1538
|
|
|
// First, try to create a better date format, ignoring the "time" elements. |
1539
|
|
|
if (preg_match('~%[AaBbCcDdeGghjmuYy](?:[^%]*%[AaBbCcDdeGghjmuYy])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) |
1540
|
|
|
$date_format = '%F'; |
1541
|
|
|
else |
1542
|
|
|
$date_format = $matches[0]; |
1543
|
|
|
|
1544
|
|
|
// We want a fairly compact version of the time, but as close as possible to the user's settings. |
1545
|
|
View Code Duplication |
if (preg_match('~%[HkIlMpPrRSTX](?:[^%]*%[HkIlMpPrRSTX])*~', $user_info['time_format'], $matches) == 0 || empty($matches[0])) |
|
|
|
|
1546
|
|
|
$time_format = '%k:%M'; |
1547
|
|
|
else |
1548
|
|
|
$time_format = str_replace(array('%I', '%H', '%S', '%r', '%R', '%T'), array('%l', '%k', '', '%l:%M %p', '%k:%M', '%l:%M'), $matches[0]); |
1549
|
|
|
|
1550
|
|
|
// Should this be an all day event? |
1551
|
|
|
$allday = (empty($row['start_time']) || empty($row['end_time']) || empty($row['timezone']) || !in_array($row['timezone'], timezone_identifiers_list(DateTimeZone::ALL_WITH_BC))) ? true : false; |
1552
|
|
|
|
1553
|
|
|
// How many days does this event span? |
1554
|
|
|
$span = 1 + date_interval_format(date_diff(date_create($row['start_date']), date_create($row['end_date'])), '%d'); |
1555
|
|
|
|
1556
|
|
|
// We need to have a defined timezone in the steps below |
1557
|
|
|
if (empty($row['timezone'])) |
1558
|
|
|
$row['timezone'] = getUserTimezone(); |
1559
|
|
|
|
1560
|
|
|
// Get most of the standard date information for the start and end datetimes |
1561
|
|
|
$start = date_parse($row['start_date'] . (!$allday ? ' ' . $row['start_time'] : '')); |
1562
|
|
|
$end = date_parse($row['end_date'] . (!$allday ? ' ' . $row['end_time'] : '')); |
1563
|
|
|
|
1564
|
|
|
// But we also want more info, so make some DateTime objects we can use |
1565
|
|
|
$start_object = date_create($row['start_date'] . (!$allday ? ' ' . $row['start_time'] : ''), timezone_open($row['timezone'])); |
1566
|
|
|
$end_object = date_create($row['end_date'] . (!$allday ? ' ' . $row['end_time'] : ''), timezone_open($row['timezone'])); |
1567
|
|
|
|
1568
|
|
|
// Unix timestamps are good |
1569
|
|
|
$start['timestamp'] = date_format($start_object, 'U'); |
1570
|
|
|
$end['timestamp'] = date_format($end_object, 'U'); |
1571
|
|
|
|
1572
|
|
|
// Datetime string without timezone (e.g. '2016-12-28 22:45:30') |
1573
|
|
|
$start['datetime'] = date_format($start_object, 'Y-m-d H:i:s'); |
1574
|
|
|
$end['datetime'] = date_format($start_object, 'Y-m-d H:i:s'); |
1575
|
|
|
|
1576
|
|
|
// ISO formatted datetime string, relative to UTC (e.g. '2016-12-29T05:45:30+00:00') |
1577
|
|
|
$start['iso_gmdate'] = gmdate('c', $start['timestamp']); |
1578
|
|
|
$end['iso_gmdate'] = gmdate('c', $end['timestamp']); |
1579
|
|
|
|
1580
|
|
|
// Strings showing the datetimes in the user's preferred format, relative to the user's time zone |
1581
|
|
|
$start['date_local'] = timeformat($start['timestamp'], $date_format); |
|
|
|
|
1582
|
|
|
$start['time_local'] = timeformat($start['timestamp'], $time_format); |
|
|
|
|
1583
|
|
|
$end['date_local'] = timeformat($end['timestamp'], $date_format); |
|
|
|
|
1584
|
|
|
$end['time_local'] = timeformat($end['timestamp'], $time_format); |
|
|
|
|
1585
|
|
|
|
1586
|
|
|
// Strings showing the datetimes in the user's preferred format, relative to the event's time zone |
1587
|
|
|
$start['date_orig'] = timeformat(strtotime(date_format($start_object, 'Y-m-d H:i:s')), $date_format, 'none'); |
|
|
|
|
1588
|
|
|
$start['time_orig'] = timeformat(strtotime(date_format($start_object, 'Y-m-d H:i:s')), $time_format, 'none'); |
|
|
|
|
1589
|
|
|
$end['date_orig'] = timeformat(strtotime(date_format($end_object, 'Y-m-d H:i:s')), $date_format, 'none'); |
|
|
|
|
1590
|
|
|
$end['time_orig'] = timeformat(strtotime(date_format($end_object, 'Y-m-d H:i:s')), $time_format, 'none'); |
|
|
|
|
1591
|
|
|
|
1592
|
|
|
// The time zone identifier (e.g. 'Europe/London') and abbreviation (e.g. 'GMT') |
1593
|
|
|
$tz = date_format($start_object, 'e'); |
1594
|
|
|
$tz_abbrev = fix_tz_abbrev($row['timezone'], date_format($start_object, 'T')); |
1595
|
|
|
|
1596
|
|
|
return array($start, $end, $allday, $span, $tz, $tz_abbrev); |
1597
|
|
|
} |
1598
|
|
|
|
1599
|
|
|
/** |
1600
|
|
|
* Gets a member's selected timezone identifier directly from the database |
1601
|
|
|
* |
1602
|
|
|
* @param int $id_member The member id to look up. If not provided, the current user's id will be used. |
1603
|
|
|
* @return string The timezone identifier string for the user's timezone. |
1604
|
|
|
*/ |
1605
|
|
|
function getUserTimezone($id_member = null) |
1606
|
|
|
{ |
1607
|
|
|
global $smcFunc, $context, $sourcedir, $user_info, $modSettings; |
1608
|
|
|
static $member_cache = array(); |
1609
|
|
|
|
1610
|
|
|
if (is_null($id_member) && $user_info['is_guest'] == false) |
1611
|
|
|
$id_member = $context['user']['id']; |
1612
|
|
|
|
1613
|
|
|
//check if the cache got the data |
1614
|
|
|
if (isset($id_member) && isset($member_cache[$id_member])) |
1615
|
|
|
{ |
1616
|
|
|
return $member_cache[$id_member]; |
1617
|
|
|
} |
1618
|
|
|
|
1619
|
|
View Code Duplication |
if (isset($id_member)) |
|
|
|
|
1620
|
|
|
{ |
1621
|
|
|
$request = $smcFunc['db_query']('', ' |
1622
|
|
|
SELECT timezone |
1623
|
|
|
FROM {db_prefix}members |
1624
|
|
|
WHERE id_member = {int:id_member}', |
1625
|
|
|
array( |
1626
|
|
|
'id_member' => $id_member, |
1627
|
|
|
) |
1628
|
|
|
); |
1629
|
|
|
list($timezone) = $smcFunc['db_fetch_row']($request); |
1630
|
|
|
$smcFunc['db_free_result']($request); |
1631
|
|
|
} |
1632
|
|
|
|
1633
|
|
View Code Duplication |
if (empty($timezone) || !in_array($timezone, timezone_identifiers_list(DateTimeZone::ALL_WITH_BC))) |
|
|
|
|
1634
|
|
|
$timezone = isset($modSettings['default_timezone']) ? $modSettings['default_timezone'] : date_default_timezone_get(); |
1635
|
|
|
|
1636
|
|
|
if (isset($id_member)) |
1637
|
|
|
$member_cache[$id_member] = $timezone; |
1638
|
|
|
|
1639
|
|
|
return $timezone; |
1640
|
|
|
} |
1641
|
|
|
|
1642
|
|
|
/** |
1643
|
|
|
* Gets all of the holidays for the listing |
1644
|
|
|
* |
1645
|
|
|
* @param int $start The item to start with (for pagination purposes) |
1646
|
|
|
* @param int $items_per_page How many items to show on each page |
1647
|
|
|
* @param string $sort A string indicating how to sort the results |
1648
|
|
|
* @return array An array of holidays, each of which is an array containing the id, year, month, day and title of the holiday |
1649
|
|
|
*/ |
1650
|
|
View Code Duplication |
function list_getHolidays($start, $items_per_page, $sort) |
|
|
|
|
1651
|
|
|
{ |
1652
|
|
|
global $smcFunc; |
1653
|
|
|
|
1654
|
|
|
$request = $smcFunc['db_query']('', ' |
1655
|
|
|
SELECT id_holiday, YEAR(event_date) AS year, MONTH(event_date) AS month, DAYOFMONTH(event_date) AS day, title |
1656
|
|
|
FROM {db_prefix}calendar_holidays |
1657
|
|
|
ORDER BY {raw:sort} |
1658
|
|
|
LIMIT {int:start}, {int:max}', |
1659
|
|
|
array( |
1660
|
|
|
'sort' => $sort, |
1661
|
|
|
'start' => $start, |
1662
|
|
|
'max' => $items_per_page, |
1663
|
|
|
) |
1664
|
|
|
); |
1665
|
|
|
$holidays = array(); |
1666
|
|
|
while ($row = $smcFunc['db_fetch_assoc']($request)) |
1667
|
|
|
$holidays[] = $row; |
1668
|
|
|
$smcFunc['db_free_result']($request); |
1669
|
|
|
|
1670
|
|
|
return $holidays; |
1671
|
|
|
} |
1672
|
|
|
|
1673
|
|
|
/** |
1674
|
|
|
* Helper function to get the total number of holidays |
1675
|
|
|
* |
1676
|
|
|
* @return int The total number of holidays |
1677
|
|
|
*/ |
1678
|
|
|
function list_getNumHolidays() |
1679
|
|
|
{ |
1680
|
|
|
global $smcFunc; |
1681
|
|
|
|
1682
|
|
|
$request = $smcFunc['db_query']('', ' |
1683
|
|
|
SELECT COUNT(*) |
1684
|
|
|
FROM {db_prefix}calendar_holidays', |
1685
|
|
|
array( |
1686
|
|
|
) |
1687
|
|
|
); |
1688
|
|
|
list($num_items) = $smcFunc['db_fetch_row']($request); |
1689
|
|
|
$smcFunc['db_free_result']($request); |
1690
|
|
|
|
1691
|
|
|
return (int) $num_items; |
1692
|
|
|
} |
1693
|
|
|
|
1694
|
|
|
/** |
1695
|
|
|
* Remove a holiday from the calendar |
1696
|
|
|
* |
1697
|
|
|
* @param array $holiday_ids An array of IDs of holidays to delete |
1698
|
|
|
*/ |
1699
|
|
|
function removeHolidays($holiday_ids) |
1700
|
|
|
{ |
1701
|
|
|
global $smcFunc; |
1702
|
|
|
|
1703
|
|
|
$smcFunc['db_query']('', ' |
1704
|
|
|
DELETE FROM {db_prefix}calendar_holidays |
1705
|
|
|
WHERE id_holiday IN ({array_int:id_holiday})', |
1706
|
|
|
array( |
1707
|
|
|
'id_holiday' => $holiday_ids, |
1708
|
|
|
) |
1709
|
|
|
); |
1710
|
|
|
|
1711
|
|
|
updateSettings(array( |
1712
|
|
|
'calendar_updated' => time(), |
1713
|
|
|
)); |
1714
|
|
|
} |
1715
|
|
|
|
1716
|
|
|
?> |
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.