diff --git a/mod/facetoface/lang/en_utf8/facetoface.php b/mod/facetoface/lang/en_utf8/facetoface.php
index 9bb825d..6817a1d 100644
--- a/mod/facetoface/lang/en_utf8/facetoface.php
+++ b/mod/facetoface/lang/en_utf8/facetoface.php
@@ -22,6 +22,8 @@ $string['bookingcompleted'] = 'Your booking has been completed.';
 $string['bookingfull'] = 'booking full';
 $string['bookingopen'] = 'booking open';
 $string['bookingstatus'] = 'You are booked for the following session';
+$string['calendareventdescriptionbooking'] = 'You are booked for this <a href=\"$a\">Face-to-face session</a>.';
+$string['calendareventdescriptionsession'] = 'You have created this <a href=\"$a\">Face-to-face session</a>.';
 $string['cancelbooking'] = 'Cancel booking';
 $string['cancelbookingfor'] = 'Cancel booking for $a';
 $string['cancellationsent'] = 'You should immediately receive a cancellation email.';
@@ -115,7 +117,9 @@ $string['facetoface:view'] = 'View face-to-face activities and sessions';
 $string['facetoface:viewattendees'] = 'View attendance list and attendees';
 $string['facetoface:viewcancellations'] = 'View cancellations';
 $string['facetoface:viewemptyactivities'] = 'View empty face-to-face activities';
+$string['facetofacebooking'] = 'Face-to-face booking';
 $string['facetofacename'] = 'Face-to-face name';
+$string['facetofacesession'] = 'Face-to-face session';
 $string['feedback'] = 'Feedback';
 $string['feedbackupdated'] = 'Feedback updated for \$a people';
 $string['floor'] = 'Floor';
diff --git a/mod/facetoface/lib.php b/mod/facetoface/lib.php
index 740bb7e..85a51a2 100644
--- a/mod/facetoface/lib.php
+++ b/mod/facetoface/lib.php
@@ -180,10 +180,10 @@ function facetoface_update_instance($facetoface) {
     $facetoface->id = $facetoface->instance;
 
     facetoface_fix_manager_messages($facetoface);
-    if ($returnid = update_record('facetoface', $facetoface)) {
+    if ($return = update_record('facetoface', $facetoface)) {
         facetoface_grade_item_update($facetoface);
     }
-    return $returnid;
+    return $return;
 }
 
 /**
@@ -271,11 +271,15 @@ function cleanup_session_data($session) {
 /**
  * Create a new entry in the facetoface_sessions table
  */
-function facetoface_add_session($session, $sessiondates) {
+function facetoface_add_session($session, $sessiondates)
+{
+    global $USER;
 
     $session->timecreated = time();
     $session = cleanup_session_data($session);
 
+    $eventname = get_field('facetoface', 'name', 'id', $session->facetoface);
+
     begin_sql();
     if ($session->id = insert_record('facetoface_sessions', $session)) {
         foreach ($sessiondates as $date) {
@@ -285,6 +289,12 @@ function facetoface_add_session($session, $sessiondates) {
                 return false;
             }
         }
+
+        // Put the sessions in this user's calendar
+        // (i.e. we're assuming it's the teacher)
+        $session->sessiondates = $sessiondates;
+        facetoface_add_session_to_user_calendar($session, $eventname, $USER->id, 'session');
+
         commit_sql();
         return $session->id;
     } else {
@@ -299,27 +309,37 @@ function facetoface_add_session($session, $sessiondates) {
 function facetoface_update_session($session, $sessiondates) {
 
     $session->timemodified = time();
-    $sessionid = $session->id;
     $session = cleanup_session_data($session);
 
     begin_sql();
-    if (!$session->id = update_record('facetoface_sessions', $session)) {
+    if (!update_record('facetoface_sessions', $session)) {
         rollback_sql();
         return false;
     }
 
-    if (!delete_records('facetoface_sessions_dates', 'sessionid', $sessionid)) {
+    if (!delete_records('facetoface_sessions_dates', 'sessionid', $session->id)) {
         rollback_sql();
         return false;
     }
     foreach ($sessiondates as $date) {
-        $date->sessionid = $sessionid;
+        $date->sessionid = $session->id;
         if (!insert_record('facetoface_sessions_dates', $date)) {
             rollback_sql();
             return false;
         }
     }
 
+    // Update Calendar entries for students and teachers
+    $session->sessiondates = $sessiondates;
+    if (!facetoface_update_calendar_events($session, 'booking')) {
+        rollback_sql();
+        return false;
+    }
+    if (!facetoface_update_calendar_events($session, 'session')) {
+        rollback_sql();
+        return false;
+    }
+
     commit_sql();
     return $session->id;
 }
@@ -353,19 +373,53 @@ function facetoface_get_facetoface_menu() {
 /**
  * Delete entry from the facetoface_sessions table along with all
  * related details in other tables
+ *
+ * @param class $formdata Data submitted by the form
  */
-function facetoface_delete_session($session) {
+function facetoface_delete_session($formdata) {
+
+    global $CFG;
+
+    $session = facetoface_get_session($formdata->s);
+    $facetoface = get_record('facetoface', 'id', $session->facetoface);
+
+    // Cancel user signups (and notify users)
+    $signedupusers = get_records_sql("SELECT DISTINCT userid
+                                        FROM {$CFG->prefix}facetoface_submissions
+                                       WHERE sessionid = $formdata->s AND
+                                             timecancelled = 0");
+    if ($signedupusers and count($signedupusers) > 0) {
+        foreach ($signedupusers as $user) {
+            if (facetoface_user_cancel($session, $user->userid)) {
+                facetoface_send_cancellation_notice($facetoface, $session, $user->userid);
+            }
+            else {
+                return false; // Cannot rollback since we notified users already
+            }
+        }
+    }
 
     begin_sql();
-    if (!delete_records('facetoface_sessions', 'id', $session->s)) {
+
+    // Remove entries from the teacher calendars
+    if (!delete_records_select('event', "modulename = 'facetoface' AND
+                                         eventtype = 'facetofacesession' AND
+                                         instance = $facetoface->id AND
+                                         description LIKE '%attendees.php?s=$session->id%'")) {
         rollback_sql();
         return false;
     }
-    if (!delete_records('facetoface_submissions', 'sessionid', $session->s)) {
+
+    // Delete session details
+    if (!delete_records('facetoface_sessions', 'id', $formdata->s)) {
         rollback_sql();
         return false;
     }
-    if (!delete_records('facetoface_sessions_dates', 'sessionid', $session->s)) {
+    if (!delete_records('facetoface_sessions_dates', 'sessionid', $formdata->s)) {
+        rollback_sql();
+        return false;
+    }
+    if (!delete_records('facetoface_submissions', 'sessionid', $formdata->s)) {
         rollback_sql();
         return false;
     }
@@ -1182,6 +1236,7 @@ function facetoface_user_signup($session, $facetoface, $course, $discountcode,
 
         if (!$notifyuser or facetoface_has_session_started($session, $timenow)) {
             // If the session has already started, there's no need to notify the user
+            facetoface_add_session_to_user_calendar($session, addslashes($facetoface->name), $userid, 'booking');
             commit_sql();
             return $return;
         }
@@ -1192,6 +1247,7 @@ function facetoface_user_signup($session, $facetoface, $course, $discountcode,
                 $usersignup->mailedconfirmation = $timenow;
 
                 if (update_record('facetoface_submissions', $usersignup)) {
+                    facetoface_add_session_to_user_calendar($session, addslashes($facetoface->name), $userid, 'booking');
                     commit_sql();
                     return $return;
                 }
@@ -1219,7 +1275,12 @@ function facetoface_user_cancel($session, $userid=false) {
         $userid = $USER->id;
     }
 
-    return facetoface_user_cancel_submission($session->id, $userid);
+    if (facetoface_user_cancel_submission($session->id, $userid)) {
+        facetoface_remove_bookings_from_user_calendar($session, $userid);
+        return true;
+    }
+
+    return false;
 }
 
 /**
@@ -2220,4 +2281,101 @@ function facetoface_user_complete($course, $user, $mod, $facetoface) {
     return true;
 }
 
+/**
+ * Add a link to the session to this user's Moodle calendar.
+ *
+ * @param class   $session     Record from the facetoface_sessions table
+ * @param class   $eventname   Name to display for this event
+ * @param integer $userid      ID of the user
+ * @param string  $eventtype   Type of the event (booking or session)
+ */
+function facetoface_add_session_to_user_calendar($session, $eventname, $userid, $eventtype)
+{
+    global $CFG;
+
+    if (!$session->datetimeknown) {
+        // There is no date associated with this session, nothing needs to be done
+        return true;
+    }
+
+    $detailsurl = $CFG->wwwroot . '/mod/facetoface/';
+    $detailsurl .= ('session' == $eventtype) ? 'attendees' : 'signup';
+    $detailsurl .= ".php?s=$session->id";
+
+    $result = true;
+    foreach ($session->sessiondates as $date) {
+        $newevent = new object();
+        $newevent->name = $eventname;
+        $newevent->description = get_string("calendareventdescription$eventtype", 'facetoface', $detailsurl);
+        $newevent->format = FORMAT_HTML;
+        $newevent->courseid = 0; // Not a course event
+        $newevent->groupid = 0;
+        $newevent->userid = $userid;
+        $newevent->instance = $session->facetoface;
+        $newevent->modulename = 'facetoface';
+        $newevent->eventtype = "facetoface$eventtype";
+        $newevent->timestart = $date->timestart;
+        $newevent->timeduration = $date->timefinish - $date->timestart;
+        $newevent->visible = 1;
+        $newevent->timemodified = time();
+
+        $result = $result && insert_record('event', $newevent);
+    }
+
+    return $result;
+}
+
+/**
+ * Remove all entries in the student's calendar which relate to this session.
+ *
+ * @param class $session    Record from the facetoface_sessions table
+ * @param integer $userid   ID of the user
+ */
+function facetoface_remove_bookings_from_user_calendar($session, $userid)
+{
+    return delete_records_select('event', "modulename = 'facetoface' AND
+                                           eventtype = 'facetofacebooking' AND
+                                           instance = $session->facetoface AND
+                                           userid = $userid");
+}
+
+/**
+ * Update the date/time of events in the Moodle Calendar when a
+ * session's dates are changed.
+ *
+ * @param class  $session    Record from the facetoface_sessions table
+ * @param string $eventtype  Type of the event (booking or session)
+ */
+function facetoface_update_calendar_events($session, $eventtype)
+{
+    global $CFG;
+
+    $whereclause = "modulename = 'facetoface' AND
+                    eventtype = 'facetoface$eventtype' AND
+                    instance = $session->facetoface";
+
+    if ('session' == $eventtype) {
+        $whereclause .= " AND description LIKE '%attendees.php?s=$session->id%'";
+    }
+
+    // Find all users with this session in their calendar
+    $users = get_records_sql("SELECT DISTINCT userid
+                                FROM {$CFG->prefix}event
+                               WHERE $whereclause");
+
+    $result = true;
+    if ($users and count($users) > 0) {
+        // Delete the existing events
+        $result = $result && delete_records_select('event', $whereclause);
+
+        // Add this session to these users' calendar
+        $eventname = get_field('facetoface', 'name', 'id', $session->facetoface);
+        foreach($users as $user) {
+            $result = $result && facetoface_add_session_to_user_calendar($session, $eventname, $user->userid, $eventtype);
+        }
+    }
+
+    return $result;
+}
+
 ?>

