From 8a7326ed4ee589338a2cd6444f681ae7570e9a0d Mon Sep 17 00:00:00 2001 From: Ankit Agarwal Date: Thu, 27 Dec 2012 15:06:37 +0800 Subject: [PATCH 1/3] MDL-36621 calendar: Ical event should display source info --- calendar/lib.php | 6 +++++- calendar/renderer.php | 5 +++++ lang/en/calendar.php | 1 + theme/base/style/calendar.css | 2 ++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/calendar/lib.php b/calendar/lib.php index dc56f91fd63..72f5c60e6bc 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -1895,7 +1895,7 @@ class calendar_event { * an event */ public function __construct($data=null) { - global $CFG, $USER; + global $CFG, $USER, $DB; // First convert to object if it is not already (should either be object or assoc array) if (!is_object($data)) { @@ -1910,6 +1910,10 @@ class calendar_event { $data->id = null; } + if (!empty($data->subscriptionid)) { + $data->subscription = $DB->get_record('event_subscriptions', array('id' => $data->subscriptionid)); + } + // Default to a user event if (empty($data->eventtype)) { $data->eventtype = 'user'; diff --git a/calendar/renderer.php b/calendar/renderer.php index b7cbd7978c8..522f1946357 100644 --- a/calendar/renderer.php +++ b/calendar/renderer.php @@ -307,6 +307,11 @@ class core_calendar_renderer extends plugin_renderer_base { if (!empty($event->courselink)) { $table->data[0]->cells[1]->text .= html_writer::tag('div', $event->courselink, array('class'=>'course')); } + if (!empty($event->subscription)) { + $table->data[0]->cells[1]->text .= html_writer::tag('div', + html_writer::link($event->subscription->url, get_string('subsource', 'calendar', + $event->subscription)), array('class' => 'subscription')); + } if (!empty($event->time)) { $table->data[0]->cells[1]->text .= html_writer::tag('span', $event->time, array('class'=>'date')); } else { diff --git a/lang/en/calendar.php b/lang/en/calendar.php index 54ee712bd48..fc84849a1cf 100644 --- a/lang/en/calendar.php +++ b/lang/en/calendar.php @@ -167,6 +167,7 @@ $string['subscriptions'] = 'Subscriptions'; $string['subscriptionname'] = 'Calendar name'; $string['subscriptionremoved'] = 'Calendar subscription {$a} removed'; $string['subscriptionupdated'] = 'Calendar subscription {$a} updated'; +$string['subsource'] = 'Event source: {$a->name}'; $string['sun'] = 'Sun'; $string['sunday'] = 'Sunday'; $string['thu'] = 'Thu'; diff --git a/theme/base/style/calendar.css b/theme/base/style/calendar.css index f6ac3820ff9..c59d76648f9 100644 --- a/theme/base/style/calendar.css +++ b/theme/base/style/calendar.css @@ -32,6 +32,8 @@ .dir-rtl.path-calendar .maincalendar .eventlist .event .topic .name {float:right;} .path-calendar .maincalendar .eventlist .event .topic .date {float:right;} .dir-rtl.path-calendar .maincalendar .eventlist .event .topic .date {float:left;} +.path-calendar .maincalendar .eventlist .event .subscription {float:left;clear:left;} +.dir-rtl.path-calendar .maincalendar .eventlist .event .subscription {float:right;clear:right;} .path-calendar .maincalendar .eventlist .event .course {float:left;clear:left;} .dir-rtl.path-calendar .maincalendar .eventlist .event .course {float:right;clear:right;} .path-calendar .maincalendar .eventlist .event .side {width:32px;} From 07c03ff96a3de1b4d296e36b93f0d98c31d3a8d7 Mon Sep 17 00:00:00 2001 From: Ankit Agarwal Date: Thu, 27 Dec 2012 16:05:24 +0800 Subject: [PATCH 2/3] MDL-36621 calendar: Display subscription info in calendar event popups --- calendar/lib.php | 11 +++++++++-- lang/en/calendar.php | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/calendar/lib.php b/calendar/lib.php index 72f5c60e6bc..3a4bc00b7b7 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -314,7 +314,7 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y if (!isset($events[$eventid])) { continue; } - $event = $events[$eventid]; + $event = new calendar_event($events[$eventid]); $popupalt = ''; $component = 'moodle'; if(!empty($event->modulename)) { @@ -335,7 +335,14 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y $popupcontent .= html_writer::start_tag('div'); $popupcontent .= $OUTPUT->pix_icon($popupicon, $popupalt, $component); - $popupcontent .= html_writer::link($dayhref, format_string($event->name, true)); + $name = format_string($event->name, true); + if (!empty($event->subscription)) { + $a = new stdClass(); + $a->name = $name; + $a->source = $event->subscription->name; + $name = get_string('namewithsource', 'calendar', $a); + } + $popupcontent .= html_writer::link($dayhref, $name); $popupcontent .= html_writer::end_tag('div'); } diff --git a/lang/en/calendar.php b/lang/en/calendar.php index fc84849a1cf..543eea2d3b3 100644 --- a/lang/en/calendar.php +++ b/lang/en/calendar.php @@ -125,6 +125,7 @@ $string['monthly'] = 'Monthly'; $string['monthlyview'] = 'Monthly view'; $string['monthnext'] = 'Next month'; $string['monththis'] = 'This month'; +$string['namewithsource'] = '{$a->name}({$a->source})'; $string['never'] = 'Never'; $string['newevent'] = 'New event'; $string['notitle'] = 'no title'; From e73b527c82be6ab30fe972a3987c83fec86ba5cb Mon Sep 17 00:00:00 2001 From: Ankit Agarwal Date: Thu, 17 Jan 2013 11:11:15 +0800 Subject: [PATCH 3/3] MDL-36621 calendar: cache calendar subscriptions and showicalsource setting Now MUC is used to cache subscription information when the constructor for an event is called, which is child of a ical subscription. A new setting calendar_showicalsource is introduced which controls if the ical source should be displayed along with events in the calendar Also minor changes has been done in places to make sure subscription id is always associated with ical events --- admin/settings/appearance.php | 1 + calendar/lib.php | 78 ++++++++++++++++++++++++----------- calendar/renderer.php | 15 +++++-- calendar/upgrade.txt | 5 +++ lang/en/admin.php | 2 + lib/db/caches.php | 10 +++++ version.php | 2 +- 7 files changed, 84 insertions(+), 29 deletions(-) diff --git a/admin/settings/appearance.php b/admin/settings/appearance.php index 99a5eea25ab..8f43cb43ee6 100644 --- a/admin/settings/appearance.php +++ b/admin/settings/appearance.php @@ -68,6 +68,7 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page $temp->add(new admin_setting_configselect('calendar_maxevents',new lang_string('configmaxevents','admin'),new lang_string('helpupcomingmaxevents', 'admin'),10,$options)); $temp->add(new admin_setting_configcheckbox('enablecalendarexport', new lang_string('enablecalendarexport', 'admin'), new lang_string('configenablecalendarexport','admin'), 1)); $temp->add(new admin_setting_configtext('calendar_exportsalt', new lang_string('calendarexportsalt','admin'), new lang_string('configcalendarexportsalt', 'admin'), random_string(60))); + $temp->add(new admin_setting_configcheckbox('calendar_showicalsource', new lang_string('configshowicalsource', 'admin'), new lang_string('helpshowicalsource','admin'), 1)); $ADMIN->add('appearance', $temp); // blog diff --git a/calendar/lib.php b/calendar/lib.php index 3a4bc00b7b7..1840f525359 100644 --- a/calendar/lib.php +++ b/calendar/lib.php @@ -119,6 +119,27 @@ function calendar_get_days() { return array('sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'); } +/** + * Get the subscription from a given id + * + * @since Moodle 2.5 + * @param int $id id of the subscription + * @return stdClass Subscription record from DB + * @throws moodle_exception for an invalid id + */ +function calendar_get_subscription($id) { + global $DB; + + $cache = cache::make('core', 'calendar_subscriptions'); + $subscription = $cache->get($id); + if (empty($subscription)) { + $subscription = $DB->get_record('event_subscriptions', array('id' => $id), '*', MUST_EXIST); + // cache the data. + $cache->set($id, $subscription); + } + return $subscription; +} + /** * Gets the first day of the week * @@ -336,7 +357,8 @@ function calendar_get_mini($courses, $groups, $users, $cal_month = false, $cal_y $popupcontent .= html_writer::start_tag('div'); $popupcontent .= $OUTPUT->pix_icon($popupicon, $popupalt, $component); $name = format_string($event->name, true); - if (!empty($event->subscription)) { + // Show ical source if needed. + if (!empty($event->subscription) && $CFG->calendar_showicalsource) { $a = new stdClass(); $a->name = $name; $a->source = $event->subscription->name; @@ -1902,7 +1924,7 @@ class calendar_event { * an event */ public function __construct($data=null) { - global $CFG, $USER, $DB; + global $CFG, $USER; // First convert to object if it is not already (should either be object or assoc array) if (!is_object($data)) { @@ -1918,7 +1940,7 @@ class calendar_event { } if (!empty($data->subscriptionid)) { - $data->subscription = $DB->get_record('event_subscriptions', array('id' => $data->subscriptionid)); + $data->subscription = calendar_get_subscription($data->subscriptionid); } // Default to a user event @@ -2754,12 +2776,18 @@ function calendar_add_subscription($sub) { $sub->pollinterval = 0; } + $cache = cache::make('core', 'calendar_subscriptions'); + if (!empty($sub->name)) { if (empty($sub->id)) { $id = $DB->insert_record('event_subscriptions', $sub); + // we cannot cache the data here because $sub is not complete. return $id; } else { + // Why are we doing an update here? $DB->update_record('event_subscriptions', $sub); + // update cache. + $cache->set($sub->id, $sub); return $sub->id; } } else { @@ -2773,9 +2801,10 @@ function calendar_add_subscription($sub) { * @param object $event The RFC-2445 iCalendar event * @param int $courseid The course ID * @param int $subscriptionid The iCalendar subscription ID + * @throws dml_exception A DML specific exception is thrown for invalid subscriptionids. * @return int Code: 1=updated, 2=inserted, 0=error */ -function calendar_add_icalendar_event($event, $courseid, $subscriptionid = null) { +function calendar_add_icalendar_event($event, $courseid, $subscriptionid) { global $DB, $USER; // Probably an unsupported X-MICROSOFT-CDO-BUSYSTATUS event. @@ -2816,16 +2845,13 @@ function calendar_add_icalendar_event($event, $courseid, $subscriptionid = null) $eventrecord->timemodified = time(); // Add the iCal subscription details if required. - if ($sub = $DB->get_record('event_subscriptions', array('id' => $subscriptionid))) { - $eventrecord->subscriptionid = $subscriptionid; - $eventrecord->userid = $sub->userid; - $eventrecord->groupid = $sub->groupid; - $eventrecord->courseid = $sub->courseid; - $eventrecord->eventtype = $sub->eventtype; - } else { - // We should never do anything with an event without a subscription reference. - return 0; - } + // We should never do anything with an event without a subscription reference. + $sub = calendar_get_subscription($subscriptionid); + $eventrecord->subscriptionid = $subscriptionid; + $eventrecord->userid = $sub->userid; + $eventrecord->groupid = $sub->groupid; + $eventrecord->courseid = $sub->courseid; + $eventrecord->eventtype = $sub->eventtype; if ($updaterecord = $DB->get_record('event', array('uuid' => $eventrecord->uuid))) { $eventrecord->id = $updaterecord->id; @@ -2849,20 +2875,18 @@ function calendar_add_icalendar_event($event, $courseid, $subscriptionid = null) * @param int $subscriptionid The ID of the subscription we are acting upon. * @param int $pollinterval The poll interval to use. * @param int $action The action to be performed. One of update or remove. + * @throws dml_exception if invalid subscriptionid is provided * @return string A log of the import progress, including errors */ function calendar_process_subscription_row($subscriptionid, $pollinterval, $action) { global $DB; - if (empty($subscriptionid)) { - return ''; - } - // Fetch the subscription from the database making sure it exists. - $sub = $DB->get_record('event_subscriptions', array('id' => $subscriptionid), '*', MUST_EXIST); + $sub = calendar_get_subscription($subscriptionid); $strupdate = get_string('update'); $strremove = get_string('remove'); + // Update or remove the subscription, based on action. switch ($action) { case $strupdate: @@ -2873,12 +2897,18 @@ function calendar_process_subscription_row($subscriptionid, $pollinterval, $acti $sub->pollinterval = $pollinterval; $DB->update_record('event_subscriptions', $sub); + // update the cache. + $cache = cache::make('core', 'calendar_subscriptions'); + $cache->set($sub->id, $sub); + // Update the events. return "

".get_string('subscriptionupdated', 'calendar', $sub->name)."

" . calendar_update_subscription_events($subscriptionid); case $strremove: $DB->delete_records('event', array('subscriptionid' => $subscriptionid)); $DB->delete_records('event_subscriptions', array('id' => $subscriptionid)); + // Invalidate cache. + cache_helper::invalidate_by_definition('core', 'calendar_subscriptions', array(), array($subscriptionid)); return get_string('subscriptionremoved', 'calendar', $sub->name); break; @@ -2973,10 +3003,7 @@ function calendar_import_icalendar_events($ical, $courseid, $subscriptionid = nu function calendar_update_subscription_events($subscriptionid) { global $DB; - $sub = $DB->get_record('event_subscriptions', array('id' => $subscriptionid)); - if (empty($sub)) { - print_error('errorbadsubscription', 'calendar'); - } + $sub = calendar_get_subscription($subscriptionid); // Don't update a file subscription. TODO: Update from a new uploaded file. if (empty($sub->url)) { return 'File subscription not updated.'; @@ -2985,6 +3012,9 @@ function calendar_update_subscription_events($subscriptionid) { $return = calendar_import_icalendar_events($ical, $sub->courseid, $subscriptionid); $sub->lastupdated = time(); $DB->update_record('event_subscriptions', $sub); + // Update the cache. + $cache = cache::make('core', 'calendar_subscriptions'); + $cache->set($subscriptionid, $sub); return $return; } @@ -3002,7 +3032,7 @@ function calendar_can_edit_subscription($subscriptionorid) { } else if (is_object($subscriptionorid)) { $subscription = $subscriptionorid; } else { - $subscription = $DB->get_record('event_subscriptions', array('id' => $subscriptionorid), '*', MUST_EXIST); + $subscription = calendar_get_subscription($subscriptionorid); } $allowed = new stdClass; $courseid = $subscription->courseid; diff --git a/calendar/renderer.php b/calendar/renderer.php index 522f1946357..752504ba6d9 100644 --- a/calendar/renderer.php +++ b/calendar/renderer.php @@ -279,6 +279,8 @@ class core_calendar_renderer extends plugin_renderer_base { * @return string */ public function event(calendar_event $event, $showactions=true) { + global $CFG; + $event = calendar_add_event_metadata($event); $anchor = html_writer::tag('a', '', array('name'=>'event_'.$event->id)); @@ -307,10 +309,15 @@ class core_calendar_renderer extends plugin_renderer_base { if (!empty($event->courselink)) { $table->data[0]->cells[1]->text .= html_writer::tag('div', $event->courselink, array('class'=>'course')); } - if (!empty($event->subscription)) { - $table->data[0]->cells[1]->text .= html_writer::tag('div', - html_writer::link($event->subscription->url, get_string('subsource', 'calendar', - $event->subscription)), array('class' => 'subscription')); + // Show subscription source if needed. + if (!empty($event->subscription) && $CFG->calendar_showicalsource) { + if (!empty($event->subscription->url)) { + $source = html_writer::link($event->subscription->url, get_string('subsource', 'calendar', $event->subscription)); + } else { + // File based ical. + $source = get_string('subsource', 'calendar', $event->subscription); + } + $table->data[0]->cells[1]->text .= html_writer::tag('div', $source, array('class' => 'subscription')); } if (!empty($event->time)) { $table->data[0]->cells[1]->text .= html_writer::tag('span', $event->time, array('class'=>'date')); diff --git a/calendar/upgrade.txt b/calendar/upgrade.txt index ff3607c1b81..673f73dc8c3 100644 --- a/calendar/upgrade.txt +++ b/calendar/upgrade.txt @@ -1,6 +1,11 @@ This files describes API changes in /calendar/* , information provided here is intended especially for developers. +=== 2.5 === +required changes in code: +* calendar_add_icalendar_event() now requires a valid subscriptionid +* calendar_process_subscription_row() throws exception for invalid subscriptionid +* calendar_update_subscription_events() now throws a dml_exception instead of moodle_exception for bad subscriptions === 2.4 === diff --git a/lang/en/admin.php b/lang/en/admin.php index eac8c6201f6..8b8b9df524a 100644 --- a/lang/en/admin.php +++ b/lang/en/admin.php @@ -307,6 +307,7 @@ $string['configsessioncookie'] = 'This setting customises the name of the cookie $string['configsessioncookiedomain'] = 'This allows you to change the domain that the Moodle cookies are available from. This is useful for Moodle customisations (e.g. authentication or enrolment plugins) that need to share Moodle session information with a web application on another subdomain. WARNING: it is strongly recommended to leave this setting at the default (empty) - an incorrect value will prevent all logins to the site.'; $string['configsessioncookiepath'] = 'If you need to change where browsers send the Moodle cookies, you can change this setting to specify a subdirectory of your web site. Otherwise the default \'/\' should be fine.'; $string['configsessiontimeout'] = 'If people logged in to this site are idle for a long time (without loading pages) then they are automatically logged out (their session is ended). This variable specifies how long this time should be.'; +$string['configshowicalsource'] = 'Show source information for ical events.'; $string['configshowcommentscount'] = 'Show comments count, it will cost one more query when display comments link'; $string['configshowsiteparticipantslist'] = 'All of these site students and site teachers will be listed on the site participants list. Who shall be allowed to see this site participants list?'; $string['configsitedefaultlicense'] = 'Default site licence'; @@ -564,6 +565,7 @@ $string['guestroleid_help'] = 'This role is automatically assigned to the guest $string['helpadminseesall'] = 'Do admins see all calendar events or just those that apply to themselves?'; $string['helpcalendarsettings'] = 'Configure various calendar and date/time-related aspects of Moodle'; $string['helpforcetimezone'] = 'You can allow users to individually select their timezone, or force a timezone for everyone.'; +$string['helpshowicalsource'] = 'Enable this setting if you want to show the ical subscription name and link for ical imported events.'; $string['helpsitemaintenance'] = 'For upgrades and other work'; $string['helpstartofweek'] = 'Which day starts the week in the calendar?'; $string['helpupcominglookahead'] = 'How many days in the future does the calendar look for upcoming events by default?'; diff --git a/lib/db/caches.php b/lib/db/caches.php index 6c3ebe0085a..4087ee3f8ad 100644 --- a/lib/db/caches.php +++ b/lib/db/caches.php @@ -75,4 +75,14 @@ $definitions = array( 'datasource' => 'question_finder', 'datasourcefile' => 'question/engine/bank.php', ), + + // Used to cache calendar subscriptions. + 'calendar_subscriptions' => array( + 'mode' => cache_store::MODE_APPLICATION, + 'requiredataguarantee' => false, + 'requiremultipleidentifiers' => false, + 'requirelockingread' => false, + 'requirelockingwrite' => false, + 'persistent' => true, + ), ); diff --git a/version.php b/version.php index 95e64ca7b96..f9fbcce30c3 100644 --- a/version.php +++ b/version.php @@ -30,7 +30,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2013011100.01; // YYYYMMDD = weekly release date of this DEV branch +$version = 2013011100.02; // YYYYMMDD = weekly release date of this DEV branch // RR = release increments - 00 in DEV branches // .XX = incremental changes