Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements recurring calendar events #8177

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
cf1ad35
Makes Time::isStrftimeFormat() public
Sesquipedalian Feb 9, 2024
9627ad8
Implements SMF\TimeInterval
Sesquipedalian Dec 28, 2023
7f48a4c
Kill off the deprecated 'span' event property
Sesquipedalian Dec 7, 2023
6b0aa4b
Moves SMF\Event to SMF\Calendar\Event
Sesquipedalian Dec 7, 2023
28deff2
Support displaying multiple events attached to one topic
Sesquipedalian Dec 7, 2023
57363c5
Implements SMF\Calendar\RRule and SMF\Calendar\RecurrenceIterator
Sesquipedalian Dec 7, 2023
6acffac
Database changes to support recurring events
Sesquipedalian Dec 7, 2023
141dc80
Adds support for showing recurring events
Sesquipedalian Dec 11, 2023
1f8f872
Adds support for creating recurring events
Sesquipedalian Dec 11, 2023
1040883
Use HTML5 date and time inputs throughout calendar UI
Sesquipedalian Dec 16, 2023
c3196c3
Implements SMF\Calendar\Holiday
Sesquipedalian Dec 18, 2023
88efeef
Implements SMF\Calendar\Birthday
Sesquipedalian Dec 16, 2023
c5d55cf
Adds support for altering event occurrences
Sesquipedalian Dec 27, 2023
b5a3825
Adds support for importing calendar data from iCal files
Sesquipedalian Jan 7, 2024
6db7551
Improves the code to export events in iCal format
Sesquipedalian Jan 8, 2024
e956769
Shows human-readable recurrence rule descriptions for recurring events
Sesquipedalian Feb 10, 2024
eaff03b
Moves calendar strings to their own file
Sesquipedalian Mar 8, 2024
f06c38a
Allow linking existing topics and events
Sesquipedalian Mar 10, 2024
1c0c52e
Adds support for subscribing to external calendars
Sesquipedalian Apr 26, 2024
93a7b26
Merge branch 'release-3.0' into recurring_events
Sesquipedalian Apr 29, 2024
253e415
Further improves the code for exporting events
Sesquipedalian Apr 29, 2024
40c90d6
Fixes CSS for dropmenu buttons created in template_button_strip()
Sesquipedalian Apr 29, 2024
fc92e92
Fixes a bug in SMF\Tasks\FetchCalendarSubscriptions
Sesquipedalian Apr 30, 2024
7c99f56
Merge branch 'release-3.0' into recurring_events
Sesquipedalian May 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Languages/en_US/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@
$txt['boards_edit'] = 'Modify Boards';
$txt['mboards_new_cat'] = 'Create new category';
$txt['manage_holidays'] = 'Manage Holidays';
$txt['calendar_import'] = 'Import Calendar Data';
$txt['calendar_settings'] = 'Calendar Settings';
$txt['search_weights'] = 'Weights';
$txt['search_method'] = 'Search Method';
Expand Down
224 changes: 224 additions & 0 deletions Languages/en_US/Calendar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
<?php

// Version: 3.0 Alpha 1; General

$txt['birthdays'] = 'Birthdays:';
$txt['events'] = 'Events:';
$txt['birthdays_upcoming'] = 'Upcoming Birthdays:';
$txt['events_upcoming'] = 'Upcoming Events:';
// Prompt for holidays in the calendar, leave blank to just display the holiday's name.
$txt['calendar_prompt'] = 'Holidays:';
$txt['calendar_month'] = 'Month';
$txt['calendar_year'] = 'Year';
$txt['calendar_day'] = 'Day';
$txt['calendar_event_title'] = 'Title';
$txt['calendar_event_options'] = 'Event Options';
$txt['calendar_post_in'] = 'Post in';
$txt['calendar_edit'] = 'Edit Event';
$txt['calendar_export'] = 'Export Event';
$txt['calendar_subscribe'] = 'Subscribe';
$txt['calendar_subscribe_desc'] = 'Shows upcoming events in your calendar app.';
$txt['calendar_subscribe_url_copied'] = 'The calendar subscription URL has been copied to the clipboard. Paste it into your calendar app to subscribe.';
$txt['calendar_download'] = 'Download';
$txt['calendar_download_desc'] = 'Exports a copy of the currently visible events.';
$txt['calendar_view_week'] = 'View Week';
$txt['event_delete_confirm'] = 'Delete this event?';
$txt['event_delete'] = 'Delete Event';
$txt['calendar_post_event'] = 'Post Event';
$txt['calendar'] = 'Calendar';
$txt['calendar_link'] = 'Add Event';
$txt['calendar_unlink'] = 'Unlink event';
$txt['calendar_link_to'] = 'Link to';
$txt['calendar_only'] = 'Calendar only';
$txt['calendar_event_new'] = 'New event';
$txt['calendar_event_existing'] = 'Existing event';
$txt['calendar_topic_existing'] = 'Existing topic';
$txt['calendar_link_event_id'] = 'Event ID';
$txt['calendar_link_topic_id'] = 'Topic ID';
$txt['calendar_upcoming'] = 'Upcoming Calendar';
$txt['calendar_today'] = 'Today’s Calendar';
$txt['calendar_week'] = 'Week';
$txt['calendar_week_beginning'] = 'Week beginning {date}';
$txt['calendar_numb_days'] = 'Number of Days';
$txt['calendar_how_edit'] = 'how do you edit these events?';
$txt['calendar_link_event'] = 'Link Event To Post';
$txt['calendar_confirm_delete'] = 'Are you sure you want to delete this event?';
$txt['calendar_linked_events'] = 'Linked Events';
$txt['calendar_click_all'] = 'Show all';
$txt['calendar_allday'] = 'All day';
$txt['calendar_timezone'] = 'Time zone';
$txt['calendar_list'] = 'List';
$txt['calendar_empty'] = 'There are no events to display.';

$txt['calendar_repeat_recurrence_label'] = 'Repeats';
$txt['calendar_repeat_interval_label'] = 'Every';
$txt['calendar_repeat_bymonthday_label'] = 'On';
$txt['calendar_repeat_byday_label'] = 'On';
$txt['calendar_repeat_bymonth_label'] = 'In';
$txt['calendar_repeat_rrule_presets'] = ['never' => 'Never', 'FREQ=DAILY' => 'Every day', 'FREQ=WEEKLY' => 'Every week', 'FREQ=MONTHLY' => 'Every month', 'FREQ=YEARLY' => 'Every year', 'custom' => 'Custom...'];
$txt['calendar_repeat_frequency_units'] = ['YEARLY' => 'year(s)', 'MONTHLY' => 'month(s)', 'WEEKLY' => 'week(s)', 'DAILY' => 'day(s)', 'HOURLY' => 'hour(s)', 'MINUTELY' => 'minute(s)', 'SECONDLY' => 'second(s)'];
$txt['calendar_repeat_until_options'] = ['forever' => 'Forever', 'until' => 'Until', 'count' => 'Number of times'];
$txt['calendar_repeat_byday_num_options'] = [1 => 'the first', 2 => 'the second', 3 => 'the third', 4 => 'the fourth', 5 => 'the fifth', -1 => 'the last', -2 => 'the second last'];
$txt['calendar_repeat_weekday'] = 'weekday';
$txt['calendar_repeat_weekend_day'] = 'weekend day';
$txt['calendar_repeat_add_condition'] = 'Add Another';
$txt['calendar_repeat_advanced_options_label'] = 'More options...';
$txt['calendar_repeat_rdates_label'] = 'Additional dates';
$txt['calendar_repeat_exdates_label'] = 'Skipped dates';
$txt['calendar_repeat_easter_w'] = 'Easter (Western)';
$txt['calendar_repeat_easter_e'] = 'Easter (Eastern)';
$txt['calendar_repeat_vernal_equinox'] = 'Vernal Equinox';
$txt['calendar_repeat_summer_solstice'] = 'Summer Solstice';
$txt['calendar_repeat_autumnal_equinox'] = 'Autumnal Equinox';
$txt['calendar_repeat_winter_solstice'] = 'Winter Solstice';
$txt['calendar_repeat_special'] = 'Special';
$txt['calendar_repeat_special_rrule_modifier'] = 'Offset';
$txt['calendar_repeat_offset_examples'] = 'e.g.: +P1D, -PT2H';
$txt['calendar_repeat_adjustment_label'] = 'Apply changes to';
$txt['calendar_repeat_adjustment_this_only'] = 'Only this occurrence';
$txt['calendar_repeat_adjustment_this_and_future'] = 'This and future occurrences';
$txt['calendar_repeat_adjustment_confirm'] = 'Are you sure you want to apply these changes to all future occurrences?-n--n-WARNING: if you select both &quot;Delete&quot; and &quot;This and future occurrences&quot;, you will delete this and all future occurrences.';
$txt['calendar_repeat_delete_label'] = 'Delete';
$txt['calendar_confirm_occurrence_delete'] = 'Are you sure you want to delete this occurrence of the event?-n--n-WARNING: if you select both &quot;Delete&quot; and &quot;This and future occurrences&quot;, you will delete this and all future occurrences.';
$txt['calendar_repeat_adjustment_edit_first'] = 'Edit original event';

// Used to show a human-readable explanation of the recurrence rule for a repeating event.
$txt['calendar_rrule_desc'] = 'Repeats {rrule_description}{start_date, select,
false {}
other {, starting {start_date}}
}.';
// 'freq' will be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, or SECONDLY, or else a named month day (e.g. "Friday the 13th").
$txt['calendar_rrule_desc_frequency_interval'] = 'every {freq, select,
YEARLY {{interval, plural,
=1 {year}
one {# year}
other {# years}
}}
MONTHLY {{interval, plural,
=1 {month}
one {# month}
other {# months}
}}
WEEKLY {{interval, plural,
=1 {week}
one {# week}
other {# weeks}
}}
DAILY {{interval, plural,
=1 {day}
one {# day}
other {# days}
}}
HOURLY {{interval, plural,
=1 {hour}
one {# hour}
other {# hours}
}}
MINUTELY {{interval, plural,
=1 {minute}
one {# minute}
other {# minutes}
}}
SECONDLY {{interval, plural,
=1 {second}
one {# second}
other {# seconds}
}}
other {{freq}}
}';
// 'freq' will be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY, or SECONDLY, or else a named month day (e.g. "Friday the 13th").
$txt['calendar_rrule_desc_frequency_interval_ordinal'] = 'every {freq, select,
YEARLY {{interval, selectordinal,
=1 {year}
one {#st year}
two {#nd year}
few {#rd year}
other {#th year}
}}
MONTHLY {{interval, selectordinal,
=1 {month}
one {#st month}
two {#nd month}
few {#rd month}
other {#th month}
}}
WEEKLY {{interval, selectordinal,
=1 {week}
one {#st week}
two {#nd week}
few {#rd week}
other {#th week}
}}
DAILY {{interval, selectordinal,
=1 {day}
one {#st day}
two {#nd day}
few {#rd day}
other {#th day}
}}
HOURLY {{interval, selectordinal,
=1 {hour}
one {#st hour}
two {#nd hour}
few {#rd hour}
other {#th hour}
}}
MINUTELY {{interval, selectordinal,
=1 {minute}
one {#st minute}
two {#nd minute}
few {#rd minute}
other {#th minute}
}}
SECONDLY {{interval, selectordinal,
=1 {second}
one {#st second}
two {#nd second}
few {#rd second}
other {#th second}
}}
other {{freq}}
}';
// 'months_titles' is a list of month names, using the forms from $txt['months_titles'].
$txt['calendar_rrule_desc_bymonth'] = 'in {months_titles}';
// 'ordinal_list' is a list of ordinal numbers (e.g. "1st, 2nd, and 3rd"). 'count' is the number of items in 'ordinal_list'.
$txt['calendar_rrule_desc_byweekno'] = '{count, plural,
one {in the {ordinal_list} week of the year}
other {in the {ordinal_list} weeks of the year}
}';
// 'ordinal_list' is a list of ordinal numbers (e.g. "1st, 2nd, and 3rd"). 'count' is the number of items in 'ordinal_list'.
$txt['calendar_rrule_desc_byyearday'] = '{count, plural,
one {on the {ordinal_list} day of the year}
other {on the {ordinal_list} days of the year}
}';
// 'ordinal_list' is a list of ordinal numbers (e.g. "1st, 2nd, and 3rd"). 'count' is the number of items in 'ordinal_list'.
$txt['calendar_rrule_desc_bymonthday'] = '{count, plural,
one {on the {ordinal_list} day of the month}
other {on the {ordinal_list} days of the month}
}';
// Translators can replace 'ordinal_month_day' with 'cardinal_month_day' in this string if the target language prefers cardinal numbers instead of ordinal numbers for this form. For example, '{day_name} the {ordinal_month_day}' will produce 'Friday the 13th', whereas '{cardinal_month_day} {day_name}' will produce '13 Friday'.
$txt['calendar_rrule_desc_named_monthday'] = '{day_name} the {ordinal_month_day}';
// 'ordinal_list' is a list of ordinal numbers (e.g. "1st, 2nd, or 3rd").
$txt['calendar_rrule_desc_named_monthdays'] = 'the first {day_name} that is the {ordinal_list} day of the month';
// E.g. "the 2nd Thursday"
$txt['calendar_rrule_desc_ordinal_day_name'] = 'the {ordinal} {day_name}';
// E.g. "on Monday", "on Tuesday and Thursday"
$txt['calendar_rrule_desc_byday'] = 'on {day_names}';
// E.g. "on every Monday", "on every Tuesday and Thursday"
$txt['calendar_rrule_desc_byday_every'] = 'on every {day_names}';
$txt['calendar_rrule_desc_byminute'] = '{minute_list} past the hour';
$txt['calendar_rrule_desc_bytime'] = 'at {times_list}';
$txt['calendar_rrule_desc_bygeneric'] = 'of {list}';
$txt['calendar_rrule_desc_between'] = 'between {min} and {max}';
$txt['calendar_rrule_desc_until'] = 'until {date}';
$txt['calendar_rrule_desc_count'] = '{count, plural,
one {for # occurrence}
other {for # occurrences}
}';
// 'ordinal_list' is a list of ordinal numbers (e.g. "1st, 2nd, and 3rd"). 'count' is the number of items in 'ordinal_list'.
$txt['calendar_rrule_desc_bysetpos'] = '{count, plural,
one {on each {ordinal_list} occurrence}
other {on each {ordinal_list} occurrences}
} of {rrule_description}';

?>
1 change: 1 addition & 0 deletions Languages/en_US/Errors.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
$txt['invalid_date'] = 'Invalid date.';
$txt['missing_event_id'] = 'Missing event ID.';
$txt['cant_edit_event'] = 'You do not have permission to edit this event.';
$txt['event_already_linked'] = 'This event is already linked to another topic.';
$txt['missing_board_id'] = 'Board ID is missing.';
$txt['missing_topic_id'] = 'Topic ID is missing.';
$txt['topic_doesnt_exist'] = 'Topic does not exist.';
Expand Down
39 changes: 3 additions & 36 deletions Languages/en_US/General.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,12 @@
$txt['days_title'] = 'Days';
$txt['days'] = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
$txt['days_short'] = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
// Months must start with 1 => 'January'. (or translated, of course.)
$txt['months_title'] = 'Months';
// Months must start with 1 => 'January' (or translated, of course).
$txt['months'] = [1 => 'January', 2 => 'February', 3 => 'March', 4 => 'April', 5 => 'May', 6 => 'June', 7 => 'July', 8 => 'August', 9 => 'September', 10 => 'October', 11 => 'November', 12 => 'December'];
// Months must start with 1 => 'January' (or translated, of course).
$txt['months_titles'] = [1 => 'January', 2 => 'February', 3 => 'March', 4 => 'April', 5 => 'May', 6 => 'June', 7 => 'July', 8 => 'August', 9 => 'September', 10 => 'October', 11 => 'November', 12 => 'December'];
// Months must start with 1 => 'Jan' (or translated, of course).
$txt['months_short'] = [1 => 'Jan', 2 => 'Feb', 3 => 'Mar', 4 => 'Apr', 5 => 'May', 6 => 'Jun', 7 => 'Jul', 8 => 'Aug', 9 => 'Sep', 10 => 'Oct', 11 => 'Nov', 12 => 'Dec'];
$txt['prev_month'] = 'Previous month';
$txt['next_month'] = 'Next month';
Expand Down Expand Up @@ -700,41 +702,6 @@
// argument(s): SMF_FULL_VERSION, SMF_SOFTWARE_YEAR, Config::$scripturl
$forum_copyright = '<a href="{scripturl}?action=credits" title="License" target="_blank" rel="noopener">{version} &copy; {year}</a>, <a href="https://www.simplemachines.org" title="Simple Machines" target="_blank" rel="noopener">Simple Machines</a>';

$txt['birthdays'] = 'Birthdays:';
$txt['events'] = 'Events:';
$txt['birthdays_upcoming'] = 'Upcoming Birthdays:';
$txt['events_upcoming'] = 'Upcoming Events:';
// Prompt for holidays in the calendar, leave blank to just display the holiday's name.
$txt['calendar_prompt'] = 'Holidays:';
$txt['calendar_month'] = 'Month';
$txt['calendar_year'] = 'Year';
$txt['calendar_day'] = 'Day';
$txt['calendar_event_title'] = 'Event Title';
$txt['calendar_event_options'] = 'Event Options';
$txt['calendar_post_in'] = 'Post in';
$txt['calendar_edit'] = 'Edit Event';
$txt['calendar_export'] = 'Export Event';
$txt['calendar_view_week'] = 'View Week';
$txt['event_delete_confirm'] = 'Delete this event?';
$txt['event_delete'] = 'Delete Event';
$txt['calendar_post_event'] = 'Post Event';
$txt['calendar'] = 'Calendar';
$txt['calendar_link'] = 'Link to Calendar';
$txt['calendar_upcoming'] = 'Upcoming Calendar';
$txt['calendar_today'] = 'Today’s Calendar';
$txt['calendar_week'] = 'Week';
$txt['calendar_week_beginning'] = 'Week beginning {date}';
$txt['calendar_numb_days'] = 'Number of Days';
$txt['calendar_how_edit'] = 'how do you edit these events?';
$txt['calendar_link_event'] = 'Link Event To Post';
$txt['calendar_confirm_delete'] = 'Are you sure you want to delete this event?';
$txt['calendar_linked_events'] = 'Linked Events';
$txt['calendar_click_all'] = 'Show all';
$txt['calendar_allday'] = 'All day';
$txt['calendar_timezone'] = 'Time zone';
$txt['calendar_list'] = 'List';
$txt['calendar_empty'] = 'There are no events to display.';

$txt['movetopic_change_subject'] = 'Change the topic’s subject';
$txt['movetopic_new_subject'] = 'New subject';
$txt['movetopic_change_all_subjects'] = 'Change every message’s subject';
Expand Down
1 change: 1 addition & 0 deletions Languages/en_US/Help.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@
$helptxt['cal_short_months'] = 'If this setting is checked, month names within the calendar will be shortened.<br><br><strong>Enabled:</strong> {short} 1<br><strong>Disabled:</strong> {long} 1';
// argument(s): $txt['days_short'][1], $txt['days'][1]
$helptxt['cal_short_days'] = 'If this setting is checked, day names within the calendar will be shortened.<br><br><strong>Enabled:</strong> {short}<br><strong>Disabled:</strong> {long}';
$helptxt['special_rrule_modifier'] = 'Use this to specify an offset from the value calculated by a special recurrence rule.<br><br>The value must be a postive or negative sign followed by an <a href="https://en.wikipedia.org/wiki/ISO_8601#Durations" class="bbc_link" target="_blank">ISO 8601 duration</a> specification. For example, "+P1D" means one day after the date calculated by the special recurrence rule, while "-P2D" means two days before.';

$helptxt['serversettings'] = '<strong>Server Settings</strong><br>
Here you can perform some core configuration for your forum. This page includes the database and URL settings, as well as other
Expand Down
14 changes: 14 additions & 0 deletions Languages/en_US/ManageCalendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@
$txt['holidays_button_edit'] = 'Edit';
$txt['holidays_button_remove'] = 'Remove';
$txt['holidays_no_entries'] = 'There are currently no holidays configured.';
$txt['holidays_date_varies'] = 'Date varies';
$txt['every_year'] = 'Every Year';

// Importing calendar data
$txt['calendar_import_desc'] = 'Here you can import holidays and events from iCalendar files.';
$txt['calendar_import_url'] = 'URL of iCalendar data';
$txt['calendar_import_url_desc'] = 'This should be the URL of an .ics file.';
$txt['calendar_import_type'] = 'Import events as';
$txt['calendar_import_type_holiday'] = 'Holidays';
$txt['calendar_import_type_event'] = 'Events';
$txt['calendar_import_button'] = 'Import';
$txt['calendar_import_subscribe'] = 'Subscribe to this calendar';
$txt['calendar_import_subscribe_desc'] = 'Calendars you subscribe to will be reimported regularly.';
$txt['calendar_import_manage_subscriptions'] = 'Subscribed calendars';
$txt['calendar_import_unsubscribe'] = 'Unsubscribe';

?>
2 changes: 2 additions & 0 deletions Languages/en_US/ManageScheduledTasks.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
$txt['scheduled_task_desc_weekly_digest'] = 'Emails out the weekly digest for notification subscribers.';
$txt['scheduled_task_fetchSMfiles'] = 'Fetch Simple Machines files';
$txt['scheduled_task_desc_fetchSMfiles'] = 'Retrieves javascript files containing notifications of updates and other information.';
$txt['scheduled_task_fetch_calendar_subs'] = 'Fetch updates from subscribed calendars';
$txt['scheduled_task_desc_fetch_calendar_subs'] = 'Updates SMF’s calendar with data from external calendars that you have subscribed to.';
$txt['scheduled_task_birthdayemails'] = 'Send Birthday emails';
$txt['scheduled_task_desc_birthdayemails'] = 'Sends out emails wishing members a happy birthday.';
$txt['scheduled_task_weekly_maintenance'] = 'Weekly Maintenance';
Expand Down
4 changes: 4 additions & 0 deletions Sources/Actions/Admin/ACP.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,10 @@ class ACP implements ActionInterface
'label' => 'manage_holidays',
'permission' => 'admin_forum',
],
'import' => [
'label' => 'calendar_import',
'permission' => 'admin_forum',
],
'settings' => [
'label' => 'calendar_settings',
'permission' => 'admin_forum',
Expand Down
Loading
Loading