/**
 * Returns the ICAL data for a facetoface meeting.
 *
 * @param integer $method The method, @see {{MDL_F2F_INVITE}}
 * @return stdClass Object that contains a filename in dataroot directory and ical template
 */
function facetoface_get_ical_attachment($method, $facetoface, $session, $user) {
    global $CFG, $DB;

    // Get user object if only id is given
    $user = (is_object($user) ? $user : $DB->get_record('user', array('id' => $user)));

    // First, generate all the VEVENT blocks
    $VEVENTS = '';
    foreach ($session->sessiondates as $date) {
        // Date that this representation of the calendar information was created -
        // we use the time the session was created
        // http://www.kanzaki.com/docs/ical/dtstamp.html
        $DTSTAMP = facetoface_ical_generate_timestamp($session->timecreated);

        // UIDs should be globally unique
        $urlbits = parse_url($CFG->wwwroot);
        $sql = "SELECT COUNT(*)
            FROM {facetoface_signups} su
            INNER JOIN {facetoface_signups_status} sus ON su.id = sus.signupid
            WHERE su.userid = ?
                AND su.sessionid = ?
                AND sus.superceded = 1
                AND sus.statuscode = ? ";
        $params = array($user->id, $session->id, MDL_F2F_STATUS_USER_CANCELLED);
        $UID =
            $DTSTAMP .
            '-' . substr(md5($CFG->siteidentifier . $session->id . $date->id), -8) .   // Unique identifier, salted with site identifier
            '-' . $DB->count_records_sql($sql, $params) .                              // New UID if this is a re-signup ;)
            '@' . $urlbits['host'];                                                    // Hostname for this moodle installation

        $DTSTART = facetoface_ical_generate_timestamp($date->timestart);
        $DTEND   = facetoface_ical_generate_timestamp($date->timefinish);

        // FIXME: currently we are not sending updates if the times of the
        // sesion are changed. This is not ideal!
        $SEQUENCE = ($method & MDL_F2F_CANCEL) ? 1 : 0;

        $SUMMARY     = str_replace("\\n", "\\n ", facetoface_ical_escape($facetoface->name, true));
        $icaldescription = get_string('icaldescription', 'facetoface', $facetoface);
        if (!empty($session->details)) {
            $icaldescription .= $session->details;
        }
        $DESCRIPTION = facetoface_ical_escape($icaldescription, true);

        // Get the location data from custom fields if they exist
        $room = facetoface_get_session_room($session->id);
        $locationstring = '';
        if (!empty($room->name)) {
            $locationstring .= $room->name;
        }
        if (!empty($room->building)) {
            if (!empty($locationstring)) {
                $locationstring .= "\n";
            }
            $locationstring .= $room->building;
        }
        if (!empty($room->address)) {
            if (!empty($locationstring)) {
                $locationstring .= "\n";
            }
            $locationstring .= $room->address;
        }

        // NOTE: Newlines are meant to be encoded with the literal sequence
        // '\n'. But evolution presents a single line text field for location,
        // and shows the newlines as [0x0A] junk. So we switch it for commas
        // here. Remember commas need to be escaped too.
        $LOCATION    = str_replace('\n', '\, ', facetoface_ical_escape($locationstring));

        $ORGANISEREMAIL = get_config(NULL, 'facetoface_fromaddress');

        $ROLE = 'REQ-PARTICIPANT';
        $CANCELSTATUS = '';
        if ($method & MDL_F2F_CANCEL) {
            $ROLE = 'NON-PARTICIPANT';
            $CANCELSTATUS = "\nSTATUS:CANCELLED";
        }

        $icalmethod = ($method & MDL_F2F_INVITE) ? 'REQUEST' : 'CANCEL';

        // FIXME: if the user has input their name in another language, we need
        // to set the LANGUAGE property parameter here
        $USERNAME = fullname($user);
        $MAILTO   = $user->email;

        $VEVENTS .= "BEGIN:VEVENT\r\n";
        $VEVENTS .= "ORGANIZER;CN={$ORGANISEREMAIL}:MAILTO:{$ORGANISEREMAIL}\r\n";
        $VEVENTS .= "DTSTART:{$DTSTART}\r\n";
        $VEVENTS .= "DTEND:{$DTEND}\r\n";
        $VEVENTS .= "LOCATION:{$LOCATION}\r\n";
        $VEVENTS .= "TRANSP:OPAQUE{$CANCELSTATUS}\r\n";
        $VEVENTS .= "SEQUENCE:{$SEQUENCE}\r\n";
        $VEVENTS .= "UID:{$UID}\r\n";
        $VEVENTS .= "DTSTAMP:{$DTSTAMP}\r\n";
        $VEVENTS .= "DESCRIPTION:{$DESCRIPTION}\r\n";
        $VEVENTS .= "SUMMARY:{$SUMMARY}\r\n";
        $VEVENTS .= "PRIORITY:5\r\n";
        $VEVENTS .= "CLASS:PUBLIC\r\n";
        $VEVENTS .= "ATTENDEE;CUTYPE=INDIVIDUAL;ROLE={$ROLE};PARTSTAT=NEEDS-ACTION;\r\n";
        $VEVENTS .= " RSVP=FALSE;CN={$USERNAME};LANGUAGE=en:MAILTO:{$MAILTO}\r\n";
        $VEVENTS .= "END:VEVENT\r\n";
    }

    $template  = "BEGIN:VCALENDAR\r\n";
    $template .= "VERSION:2.0\r\n";
    $template .= "PRODID:-//Moodle//NONSGML Facetoface//EN\r\n";
    $template .= "METHOD:{$icalmethod}\r\n";
    $template .= "{$VEVENTS}";
    $template .= "END:VCALENDAR\r\n";

    $tempfilename = md5($template);
    $tempfilepathname = $CFG->dataroot . '/' . $tempfilename;
    file_put_contents($tempfilepathname, $template);

    $ical = new stdClass();
    $ical->file = $tempfilename;
    $ical->content = $template;
    return $ical;
}
Beispiel #2
0
/**
 * Returns the ICAL data for a facetoface meeting.
 *
 * @param integer $method The method, @see {{MDL_F2F_INVITE}}
 * @param object $facetoface A face-to-face object containing activity details
 * @param object $session A session object containing session details
 * @return string Filename of the attachment in the temp directory
 */
function facetoface_get_ical_attachment($method, $facetoface, $session, $user)
{
    global $CFG, $DB;
    // First, generate all the VEVENT blocks.
    $VEVENTS = '';
    foreach ($session->sessiondates as $date) {
        /*
         * Date that this representation of the calendar information was created -
         * we use the time the session was created
         * http://www.kanzaki.com/docs/ical/dtstamp.html
         */
        $DTSTAMP = facetoface_ical_generate_timestamp($session->timecreated);
        // UIDs should be globally unique.
        $urlbits = parse_url($CFG->wwwroot);
        $sql = "SELECT COUNT(*)\n            FROM {facetoface_signups} su\n            INNER JOIN {facetoface_signups_status} sus ON su.id = sus.signupid\n            WHERE su.userid = ?\n                AND su.sessionid = ?\n                AND sus.superceded = 1\n                AND sus.statuscode = ? ";
        $params = array($user->id, $session->id, MDL_F2F_STATUS_USER_CANCELLED);
        $UID = $DTSTAMP . '-' . substr(md5($CFG->siteidentifier . $session->id . $date->id), -8) . '-' . $DB->count_records_sql($sql, $params) . '@' . $urlbits['host'];
        // Hostname for this moodle installation.
        $DTSTART = facetoface_ical_generate_timestamp($date->timestart);
        $DTEND = facetoface_ical_generate_timestamp($date->timefinish);
        // FIXME: currently we are not sending updates if the times of the session are changed. This is not ideal!
        $SEQUENCE = $method & MDL_F2F_CANCEL ? 1 : 0;
        $SUMMARY = facetoface_ical_escape($facetoface->name);
        $DESCRIPTION = facetoface_ical_escape($session->details, true);
        // Get the location data from custom fields if they exist.
        $customfielddata = facetoface_get_customfielddata($session->id);
        $locationstring = '';
        if (!empty($customfielddata['room'])) {
            $locationstring .= $customfielddata['room']->data;
        }
        if (!empty($customfielddata['venue'])) {
            if (!empty($locationstring)) {
                $locationstring .= "\n";
            }
            $locationstring .= $customfielddata['venue']->data;
        }
        if (!empty($customfielddata['location'])) {
            if (!empty($locationstring)) {
                $locationstring .= "\n";
            }
            $locationstring .= $customfielddata['location']->data;
        }
        /*
         * NOTE: Newlines are meant to be encoded with the literal sequence
         * '\n'. But evolution presents a single line text field for location,
         * and shows the newlines as [0x0A] junk. So we switch it for commas
         * here. Remember commas need to be escaped too.
         */
        $LOCATION = str_replace('\\n', '\\, ', facetoface_ical_escape($locationstring));
        $ORGANISEREMAIL = get_config(null, 'facetoface_fromaddress');
        $ROLE = 'REQ-PARTICIPANT';
        $CANCELSTATUS = '';
        if ($method & MDL_F2F_CANCEL) {
            $ROLE = 'NON-PARTICIPANT';
            $CANCELSTATUS = "\nSTATUS:CANCELLED";
        }
        $icalmethod = $method & MDL_F2F_INVITE ? 'REQUEST' : 'CANCEL';
        // FIXME: if the user has input their name in another language, we need to set the LANGUAGE property parameter here.
        $USERNAME = fullname($user);
        $MAILTO = $user->email;
        // The extra newline at the bottom is so multiple events start on their own lines. The very last one is trimmed outside the loop.
        $VEVENTS .= <<<EOF
BEGIN:VEVENT
UID:{$UID}
DTSTAMP:{$DTSTAMP}
DTSTART:{$DTSTART}
DTEND:{$DTEND}
SEQUENCE:{$SEQUENCE}
SUMMARY:{$SUMMARY}
LOCATION:{$LOCATION}
DESCRIPTION:{$DESCRIPTION}
CLASS:PRIVATE
TRANSP:OPAQUE{$CANCELSTATUS}
ORGANIZER;CN={$ORGANISEREMAIL}:MAILTO:{$ORGANISEREMAIL}
ATTENDEE;CUTYPE=INDIVIDUAL;ROLE={$ROLE};PARTSTAT=NEEDS-ACTION;
 RSVP=FALSE;CN={$USERNAME};LANGUAGE=en:MAILTO:{$MAILTO}
END:VEVENT

EOF;
    }
    $VEVENTS = trim($VEVENTS);
    // TODO: remove the hard-coded timezone!.
    $template = <<<EOF
BEGIN:VCALENDAR
CALSCALE:GREGORIAN
PRODID:-//Moodle//NONSGML Facetoface//EN
VERSION:2.0
METHOD:{$icalmethod}
BEGIN:VTIMEZONE
TZID:/softwarestudio.org/Tzfile/Pacific/Auckland
X-LIC-LOCATION:Pacific/Auckland
BEGIN:STANDARD
TZNAME:NZST
DTSTART:19700405T020000
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=1SU;BYMONTH=4
TZOFFSETFROM:+1300
TZOFFSETTO:+1200
END:STANDARD
BEGIN:DAYLIGHT
TZNAME:NZDT
DTSTART:19700928T030000
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=9
TZOFFSETFROM:+1200
TZOFFSETTO:+1300
END:DAYLIGHT
END:VTIMEZONE
{$VEVENTS}
END:VCALENDAR
EOF;
    $tempfilename = md5($template);
    $tempfilepathname = $CFG->dataroot . '/' . $tempfilename;
    file_put_contents($tempfilepathname, $template);
    return $tempfilename;
}
    function test_facetoface_ical_escape() {
        // Define test variables.
        $text1 = "this is a test!&nbsp";
        $text2 = NULL;
        $text3 = "This string should start repeating at 75 charaters for three repetitions. "
            . "This string should start repeating at 75 charaters for three repetitions. "
            . "This string should start repeating at 75 charaters for three repetitions.";
        $text4 = "/'s ; \" ' \n , . & &nbsp;";

        $converthtml1 = FALSE;
        $converthtml2 = TRUE;

        // Tests.
        $this->assertEquals(facetoface_ical_escape($text1, $converthtml1), $text1);
        $this->assertEquals(facetoface_ical_escape($text1, $converthtml2), $text1);

        $this->assertEquals(facetoface_ical_escape($text2, $converthtml1), $text2);
        $this->assertEquals(facetoface_ical_escape($text2, $converthtml2), $text2);

        $this->assertEquals(facetoface_ical_escape($text3, $converthtml1),
            "This string should start repeating at 75 charaters for three repetitions. \n "
            . "This string should start repeating at 75 charaters for three repetitions. \n "
            . "This string should start repeating at 75 charaters for three repetitions.");
        $this->assertEquals(facetoface_ical_escape($text3, $converthtml2),
            "This string should start repeating at 75 charaters for three repetitions. \n "
            . "This string should start repeating at 75 charaters for three repetitions. \n "
            . "This string should start repeating at 75 charaters for three repetitions.");

        $this->assertEquals(facetoface_ical_escape($text4, $converthtml1), "/'s \; \\\" ' \\n \, . & &nbsp\;");
        $this->assertEquals(facetoface_ical_escape($text4, $converthtml2), "/'s \; \\\" ' \, . & ");

        $this->resetAfterTest(true);
    }