* Added a bit of AMOS to copy existing strings and save a little translation effort
* Cleaned up fixed strings in several places
* Cleaned up some existing strings as required.
* Fixed install and upgrade code. Split upgrade into two parts (one for each table).
* Fixed fatal error caused by missing forms lib inclusion
* Added param types to forms.
* Converted file_get_content to use curl for URL's.
* Cleaned things up per coding style.
* Separated subscription management and form into separate files.
* Tidied up bennu inclusion to just where required.
* Lots of other small fixes as well.
AMOS BEGIN
CPY [calendar,calendar],[colcalendar,calendar]
CPY [actions,moodle],[actions,calendar]
CPY [never,moodle],[never,calendar]
AMOS END
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-require_once($CFG->libdir.'/bennu/bennu.inc.php');
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
+}
/**
* These are read by the administration component to provide default values
return '';
}
if (!($linkbase instanceof moodle_url)) {
- $linkbase = new moodle_url();
+ $linkbase = new moodle_url($linkbase);
}
if (!empty($d)) {
$linkbase->param('cal_d', $d);
$cm = get_coursemodule_from_instance($data->modulename, $data->instance, 0, false, MUST_EXIST);
$context = context_course::instance($cm->course);
} else {
- $context = context_user::instance();
+ $context = context_user::instance($data->userid);
}
return $context;
return make_timestamp($this->year, $this->month, $this->day+1);
}
/**
- * Adds the pretend blocks for teh calendar
+ * Adds the pretend blocks for the calendar
*
* @param core_calendar_renderer $renderer
* @param bool $showfilters display filters, false is set as default
}
/**
- * Returns option list for the pollinterval setting.
- * @return array option list
+ * Returns option list for the poll interval setting.
+ *
+ * @return array An array of poll interval options. Interval => description.
*/
function calendar_get_pollinterval_choices() {
return array(
- '0' => get_string('never', 'calendar'),
- '3600' => get_string('hourly', 'calendar'),
- '86400' => get_string('daily', 'calendar'),
- '604800' => get_string('weekly', 'calendar'),
- '2628000' => get_string('monthly', 'calendar'),
- '31536000' => get_string('annually', 'calendar'),
- );
+ '0' => new lang_string('never', 'calendar'),
+ '3600' => new lang_string('hourly', 'calendar'),
+ '86400' => new lang_string('daily', 'calendar'),
+ '604800' => new lang_string('weekly', 'calendar'),
+ '2628000' => new lang_string('monthly', 'calendar'),
+ '31536000' => new lang_string('annually', 'calendar')
+ );
}
/**
- * Returns option list of available options for the calendar event type, given
- * the current user and course.
+ * Returns option list of available options for the calendar event type, given the current user and course.
+ *
* @param int $courseid The id of the course
- * @return array option list
+ * @return array An array containing the event types the user can create.
*/
function calendar_get_eventtype_choices($courseid) {
$choices = array();
return array($choices, $allowed->groups);
}
-/**
- * Form for adding a subscription to a Moodle course calendar.
- */
-class calendar_addsubscription_form extends moodleform {
-
- function definition() {
- $mform =& $this->_form;
- $courseid = optional_param('course', 0, PARAM_INT);
-
- // code to show/hide the form from the heading
- $mform->addElement('html', '<script type="text/javascript"><!--
- function showhide_subform() {
- divs = document.getElementById("addsubscriptionform").getElementsByTagName("div");
- for (var i = 0; i < divs.length; ++i) {
- if (divs[i].style.display=="none") {
- divs[i].style.display = "block";
- } else {
- divs[i].style.display = "none";
- }
- }
- }
- //--></script>');
- $mform->addElement('header', 'addsubscriptionform', '<a name="targetsubcriptionform" onclick="showhide_subform()">'.get_string('importcalendarheading', 'calendar').'</a>');
-
- $mform->addElement('text', 'name', get_string('subscriptionname', 'calendar'), 'maxlength="255" size="40"');
- $mform->addRule('name', get_string('required'), 'required');
-
- $mform->addElement('html', get_string('importfrominstructions', 'calendar'));
- $choices = array(CALENDAR_IMPORT_FROM_FILE => get_string('importfromfile', 'calendar'),
- CALENDAR_IMPORT_FROM_URL => get_string('importfromurl', 'calendar'));
- $mform->addElement('select', 'importfrom', get_string('importcalendarfrom', 'calendar'), $choices);
- $mform->setDefault('importfrom', CALENDAR_IMPORT_FROM_URL);
-
- $mform->addElement('text', 'url', get_string('importfromurl', 'calendar'), 'maxlength="255" size="50"');
- $mform->addElement('filepicker', 'importfile', get_string('importfromfile', 'calendar'));
-
- $mform->disabledIf('url', 'importfrom', 'eq', CALENDAR_IMPORT_FROM_FILE);
- $mform->disabledIf('importfile', 'importfrom', 'eq', CALENDAR_IMPORT_FROM_URL);
-
- $choices = calendar_get_pollinterval_choices();
- $mform->addElement('select', 'pollinterval', get_string('pollinterval', 'calendar'), $choices);
-
- $mform->setDefault('pollinterval', 604800);
- $mform->addHelpButton('pollinterval', 'pollinterval', 'calendar');
-
- // eventtype: 0 = user, 1 = global, anything else = course ID
- list($choices, $groups) = calendar_get_eventtype_choices($courseid);
- $mform->addElement('select', 'eventtype', get_string('eventkind', 'calendar'), $choices);
- $mform->addRule('eventtype', get_string('required'), 'required');
-
- if (!empty($groups) and is_array($groups)) {
- $groupoptions = array();
- foreach ($groups as $group) {
- $groupoptions[$group->id] = $group->name;
- }
- $mform->addElement('select', 'groupid', get_string('typegroup', 'calendar'), $groupoptions);
- $mform->disabledIf('groupid', 'eventtype', 'noteq', 'group');
- }
-
- $mform->addElement('hidden', 'course', optional_param('course', 0, PARAM_INT));
- $mform->addElement('hidden', 'view', optional_param('view', 'upcoming', PARAM_ALPHA));
- $mform->addElement('hidden', 'cal_d', optional_param('cal_d', 0, PARAM_INT));
- $mform->addElement('hidden', 'cal_m', optional_param('cal_m', 0, PARAM_INT));
- $mform->addElement('hidden', 'cal_y', optional_param('cal_y', 0, PARAM_INT));
- $mform->addElement('hidden', 'id', optional_param('id', 0, PARAM_INT));
-
- $mform->addElement('submit', 'add', get_string('add'));
-
- // *sigh* folding up the form breaks the filepicker control
- // $mform->addElement('html', '<script type="text/javascript">showhide_subform()</script>');
- }
-
- function get_ical_data() {
- $formdata = $this->get_data();
- switch ($formdata->importfrom) {
- case CALENDAR_IMPORT_FROM_FILE:
- $calendar = $this->get_file_content('importfile');
- break;
- case CALENDAR_IMPORT_FROM_URL:
- $calendar = download_file_content($formdata->importurl);
- break;
- }
- return $calendar;
- }
-}
-
/**
* Add an iCalendar subscription to the database.
- * @param object $sub The subscription object (e.g. from the form)
- * @return int The insert ID, if any.
+ *
+ * @param stdClass $sub The subscription object (e.g. from the form)
+ * @return int The insert ID, if any.
*/
function calendar_add_subscription($sub) {
global $DB, $USER;
+
$sub->courseid = $sub->eventtype;
if ($sub->eventtype == 'group') {
$sub->courseid = $sub->course;
}
$sub->userid = $USER->id;
- // file subscriptions never update.
+ // File subscriptions never update.
if (empty($sub->url)) {
$sub->pollinterval = 0;
}
/**
* Add an iCalendar event to the Moodle calendar.
- * @param object $event The RFC-2445 iCalendar event
- * @param int $courseid The course ID
- * @param int $subscriptionid The iCalendar subscription ID
- * @return int Code: 1=updated, 2=inserted, 0=error
+ *
+ * @param object $event The RFC-2445 iCalendar event
+ * @param int $courseid The course ID
+ * @param int $subscriptionid The iCalendar subscription ID
+ * @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 = null) {
global $DB, $USER;
- $eventrecord = new stdClass;
-
- // probably an unsupported X-MICROSOFT-CDO-BUSYSTATUS event.
+ // Probably an unsupported X-MICROSOFT-CDO-BUSYSTATUS event.
if (empty($event->properties['SUMMARY'])) {
return 0;
}
$name = str_replace('\n', '<br />', $name);
$name = str_replace('\\', '', $name);
$name = preg_replace('/\s+/', ' ', $name);
+
+ $eventrecord = new stdClass;
$eventrecord->name = clean_param($name, PARAM_NOTAGS);
if (empty($event->properties['DESCRIPTION'][0]->value)) {
}
$eventrecord->description = clean_param($description, PARAM_NOTAGS);
- // probably a repeating event with RRULE etc. TODO: skip for now
+ // Probably a repeating event with RRULE etc. TODO: skip for now.
if (empty($event->properties['DTSTART'][0]->value)) {
return 0;
}
$eventrecord->uuid = $event->properties['UID'][0]->value;
$eventrecord->timemodified = time();
- // Add the iCal subscription details if required
+ // Add the iCal subscription details if required.
if ($sub = $DB->get_record('event_subscriptions', array('id' => $subscriptionid))) {
$eventrecord->subscriptionid = $subscriptionid;
$eventrecord->userid = $sub->userid;
}
/**
- * Create the list of iCalendar subscriptions for a course calendar.
- * @param int $courseid The course ID
- * @return string The table output.
- */
-function calendar_show_subscriptions($courseid, $importresults='') {
- global $DB, $OUTPUT, $CFG, $USER;
-
- $view = optional_param('view', '', PARAM_ALPHA);
- $sesskey = sesskey();
- $out = '';
-
- $str = new object();
- $str->update = get_string('update');
- $str->remove = get_string('remove');
- $str->add = get_string('add');
- $str->colcalendar = get_string('colcalendar', 'calendar');
- $str->collastupdated = get_string('collastupdated', 'calendar');
- $str->colpoll = get_string('colpoll', 'calendar');
- $str->colactions = get_string('colactions', 'calendar');
- $str->nocalendarsubscriptions = get_string('nocalendarsubscriptions', 'calendar');
-
- $out .= $OUTPUT->box_start('generalbox calendarsubs');
- $out .= $importresults;
-
- $table = new html_table();
- $table->head = array($str->colcalendar, $str->collastupdated, $str->colpoll, $str->colactions);
- $table->align = array('left', 'left', 'left', 'center');
- $table->width = '100%';
- $table->data = array();
-
- $subs = $DB->get_records_sql('select * from {event_subscriptions}
- where courseid = :courseid
- or (courseid = 0 and userid = :userid)',
- array('courseid' => $courseid, 'userid' => $USER->id));
- if (empty($subs)) {
- $c = new html_table_cell($str->nocalendarsubscriptions);
- $c->colspan = 4;
- $table->data[] = new html_table_row(array($c));
- }
- foreach ($subs as $id => $sub) {
- $label = empty($sub->url) ? $sub->name : "<a href=\"{$sub->url}\">{$sub->name}</a>";
- $cellurl = new html_table_cell($label);
- $lastupdated = empty($sub->lastupdated)
- ? get_string('never', 'calendar')
- : userdate($sub->lastupdated, get_string('strftimedatetimeshort', 'langconfig'));
- $cellupdated = new html_table_cell($lastupdated);
-
- if (empty($sub->url)) {
- // don't update an iCal file, which has no URL.
- $pollinterval = '<input type="hidden" name="pollinterval" value="0" />';
- } else {
- // assemble pollinterval control
- $pollinterval = "<div style=\"float:left\">
- <select name=\"pollinterval\">\n";
- foreach (calendar_get_pollinterval_choices() as $k => $v) {
- $selected = ($k == $sub->pollinterval) ? ' selected' : '';
- $pollinterval .= "<option value=\"{$k}\"{$selected}>{$v}</option>\n";
- }
- $pollinterval .= "</select></div>";
- }
-
- // assemble form for the subscription row
- $rowform = "
- <form action=\"{$CFG->wwwroot}/calendar/view.php\" method=\"post\">
- {$pollinterval}
- <div style=\"float:right\">
- <input type=\"hidden\" name=\"sesskey\" value=\"{$sesskey}\" />
- <input type=\"hidden\" name=\"view\" value=\"{$view}\" />
- <input type=\"hidden\" name=\"course\" value=\"{$courseid}\" />
- <input type=\"hidden\" name=\"id\" value=\"{$sub->id}\" />
- " . (empty($sub->url)
- ? ''
- : "<input type=\"submit\" name=\"action\" value=\"{$str->update}\" />") . "
- <input type=\"submit\" name=\"action\" value=\"{$str->remove}\" />
- </div>
- </form>";
- $cellform = new html_table_cell($rowform);
- $cellform->colspan = 2;
- $table->data[] = new html_table_row(array($cellurl, $cellupdated, $cellform));
- }
- $out .= html_writer::table($table);
-
- // form for adding a new subscription
- $form = new calendar_addsubscription_form();
- $formdata = $form->get_data();
- if (empty($formdata)) {
- $formdata = new stdClass;
- $formdata->course = $courseid;
- $form->set_data($formdata);
- }
-
- // *sigh* there appears to be no function that returns Moodle Form HTML.
- ob_start();
- $form->display();
- $buffer = ob_get_contents();
- $out .= $buffer;
- ob_end_clean();
-
- $out .= $OUTPUT->box_end();
- return $out;
-}
-
-/**
- * Add a subscription from the form data and add its events to the calendar.
- * The form data will be either from the new subscription form, or from a form
- * on one of the rows in the existing subscriptions table.
- * @param int $courseid The course ID
- * @return string A log of the import progress, including errors
- */
-function calendar_process_subscription_form($courseid) {
- global $DB;
-
- $form = new calendar_addsubscription_form();
- $formdata = $form->get_data();
- if (!empty($formdata)) {
- if (empty($formdata->url) and empty($formdata->importfile)) {
- print_error('errorrequiredurlorfile', 'calendar');
- }
- if ($formdata->importfrom == CALENDAR_IMPORT_FROM_FILE) {
- // blank the URL if it's a file import
- $formdata->url = '';
- $subscriptionid = calendar_add_subscription($formdata);
- $calendar = $form->get_ical_data();
- $ical = new iCalendar();
- $ical->unserialize($calendar);
- return calendar_import_icalendar_events($ical, $courseid, $subscriptionid);
- } else {
- $subscriptionid = calendar_add_subscription($formdata);
- return calendar_update_subscription_events($subscriptionid);
- }
- } else {
- // process any subscription row form data
- return calendar_process_subscription_row();
- }
-}
-
-/**
- * Update a subscription from the form data in one of the rows in the existing
- * subscriptions table.
- * @return string A log of the import progress, including errors
+ * Update a subscription from the form data in one of the rows in the existing subscriptions table.
+ *
+ * @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.
+ * @return string A log of the import progress, including errors
*/
-function calendar_process_subscription_row() {
+function calendar_process_subscription_row($subscriptionid, $pollinterval, $action) {
global $DB;
- $id = optional_param('id', 0, PARAM_INT);
- $courseid = optional_param('course', 0, PARAM_INT);
- $pollinterval = optional_param('pollinterval', 0, PARAM_INT);
- $action = optional_param('action', '', PARAM_ALPHA);
-
- if (empty($id)) {
+ if (empty($subscriptionid)) {
return '';
}
- $str->update = get_string('update');
- $str->remove = get_string('remove');
+ // Fetch the subscription from the database making sure it exists.
+ $sub = $DB->get_record('event_subscriptions', array('id' => $subscriptionid), '*', MUST_EXIST);
- // update or remove the subscription, based on action.
- $sub = $DB->get_record('event_subscriptions', array('id' => $id), '*', MUST_EXIST);
+ $strupdate = get_string('update');
+ $strremove = get_string('remove');
+ // Update or remove the subscription, based on action.
switch ($action) {
- case $str->update:
- // skip updating file subscriptions
- if (empty($sub->url)) {
- break;
- }
- $sub->pollinterval = $pollinterval;
- $DB->update_record('event_subscriptions', $sub);
+ case $strupdate:
+ // Skip updating file subscriptions.
+ if (empty($sub->url)) {
+ break;
+ }
+ $sub->pollinterval = $pollinterval;
+ $DB->update_record('event_subscriptions', $sub);
- // update the events
- return "<p>Calendar subscription '{$sub->name}' updated.</p>" . calendar_update_subscription_events($id);
- break;
+ // Update the events.
+ return "<p>".get_string('subscriptionupdated', 'calendar', $sub->name)."</p>" . calendar_update_subscription_events($subscriptionid);
- case $str->remove:
- $sesskey = required_param('sesskey', PARAM_ALPHANUM);
- $DB->delete_records('event', array('subscriptionid' => $id));
- $DB->delete_records('event_subscriptions', array('id' => $id));
- return "Calendar subscription '{$sub->name}' removed.";
- break;
+ case $strremove:
+ $DB->delete_records('event', array('subscriptionid' => $subscriptionid));
+ $DB->delete_records('event_subscriptions', array('id' => $subscriptionid));
+ return get_string('subscriptionremoved', 'calendar', $sub->name);
+ break;
- default:
- break;
+ default:
+ break;
}
return '';
}
/**
* From a URL, fetch the calendar and return an iCalendar object.
- * @param string $url The iCalendar URL
- * @return object The iCalendar object
+ *
+ * @param string $url The iCalendar URL
+ * @return stdClass The iCalendar object
*/
function calendar_get_icalendar($url) {
- $calendar = file_get_contents($url);
+ global $CFG;
+
+ require_once($CFG->libdir.'/filelib.php');
+
+ $curl = new curl();
+ $calendar = $curl->get($url);
+ if (!$calendar) {
+ throw new moodle_exception('errorinvalidicalurl', 'calendar');
+ }
+
$ical = new iCalendar();
$ical->unserialize($calendar);
return $ical;
/**
* Import events from an iCalendar object into a course calendar.
- * @param object $ical The iCalendar object
- * @param integer $courseid The course ID for the calendar
- * @param integer $subscriptionid The subscription ID
- * @return string A log of the import progress, including
- * errors
+ *
+ * @param stdClass $ical The iCalendar object.
+ * @param int $courseid The course ID for the calendar.
+ * @param int $subscriptionid The subscription ID.
+ * @return string A log of the import progress, including errors.
*/
-function calendar_import_icalendar_events($ical, $courseid, $subscriptionid=null) {
+function calendar_import_icalendar_events($ical, $courseid, $subscriptionid = null) {
global $DB;
$return = '';
$eventcount = 0;
$updatecount = 0;
- // large calendars take a while...
- ini_set('max_execution_time', 300);
+ // Large calendars take a while...
+ set_time_limit(300);
- // mark all events in a subscription with a zero timestamp
+ // Mark all events in a subscription with a zero timestamp.
if (!empty($subscriptionid)) {
- $sql = "update {event} set timemodified = :time where subscriptionid = :id";
+ $sql = "UPDATE {event} SET timemodified = :time WHERE subscriptionid = :id";
$DB->execute($sql, array('time' => 0, 'id' => $subscriptionid));
}
foreach ($ical->components['VEVENT'] as $event) {
break;
}
}
- $return .= "<p> ".get_string('eventsimported', 'calendar').": {$eventcount} </p>\n";
- $return .= "<p> ".get_string('eventsupdated', 'calendar').": {$updatecount} </p>\n";
+ $return .= "<p> ".get_string('eventsimported', 'calendar', $eventcount)."</p>";
+ $return .= "<p> ".get_string('eventsupdated', 'calendar', $updatecount)."</p>";
- // delete remaining zero-marked events since they're not in remote calendar
+ // Delete remaining zero-marked events since they're not in remote calendar.
if (!empty($subscriptionid)) {
$deletecount = $DB->count_records('event', array('timemodified' => 0, 'subscriptionid' => $subscriptionid));
if (!empty($deletecount)) {
- $sql = "delete from {event} where timemodified = :time and subscriptionid = :id";
+ $sql = "DELETE FROM {event} WHERE timemodified = :time AND subscriptionid = :id";
$DB->execute($sql, array('time' => 0, 'id' => $subscriptionid));
$return .= "<p> ".get_string('eventsdeleted', 'calendar').": {$deletecount} </p>\n";
}
/**
* Fetch a calendar subscription and update the events in the calendar.
- * @param integer $subscriptionid The course ID for the calendar
- * @return string A log of the import progress, including
- * errors
+ *
+ * @param int $subscriptionid The course ID for the calendar.
+ * @return string A log of the import progress, including errors.
*/
function calendar_update_subscription_events($subscriptionid) {
global $DB;
- $return = '';
$sub = $DB->get_record('event_subscriptions', array('id' => $subscriptionid));
if (empty($sub)) {
print_error('errorbadsubscription', 'calendar');
}
- // Don't update a file subscription. TODO: Update from a new uploaded file?
+ // Don't update a file subscription. TODO: Update from a new uploaded file.
if (empty($sub->url)) {
return 'File subscription not updated.';
}
/**
* Update calendar subscriptions.
+ *
+ * @return bool
*/
function calendar_cron() {
- global $DB;
+ global $CFG, $DB;
+
+ // In order to execute this we need bennu.
+ require_once($CFG->libdir.'/bennu/bennu.inc.php');
+
mtrace(get_string('cronupdate', 'calendar'));
+
$time = time();
- $subscriptions = $DB->get_records_sql('select * from {event_subscriptions} where pollinterval > 0 and lastupdated + pollinterval < ?', array($time));
+ $subscriptions = $DB->get_records_sql('SELECT * FROM {event_subscriptions} WHERE pollinterval > 0 AND lastupdated + pollinterval < ?', array($time));
foreach ($subscriptions as $sub) {
mtrace(get_string('cronupdatesub', 'calendar', $sub));
- $log = calendar_update_subscription_events($sub->id);
+ try {
+ $log = calendar_update_subscription_events($sub->id);
+ } catch (moodle_exception $ex) {
+
+ }
mtrace(trim(strip_tags($log)));
}
+
mtrace(get_string('cronupdatefinished', 'calendar'));
- return true;
-}
+ return true;
+}
\ No newline at end of file
--- /dev/null
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Allows the user to manage calendar subscriptions.
+ *
+ * @copyright 2012 Jonathan Harker
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package calendar
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/bennu/bennu.inc.php');
+require_once($CFG->dirroot.'/course/lib.php');
+require_once($CFG->dirroot.'/calendar/lib.php');
+require_once($CFG->dirroot.'/calendar/managesubscriptions_form.php');
+
+// Required use.
+$courseid = optional_param('course', SITEID, PARAM_INT);
+// Used for processing subscription actions.
+$subscriptionid = optional_param('id', 0, PARAM_INT);
+$pollinterval = optional_param('pollinterval', 0, PARAM_INT);
+$action = optional_param('action', '', PARAM_ALPHA);
+
+$url = new moodle_url('/calendar/managesubscriptions.php');
+if ($courseid != SITEID) {
+ $url->param('course', $courseid);
+}
+navigation_node::override_active_url(new moodle_url('/calendar/view.php', array('view' => 'month')));
+$PAGE->set_url($url);
+$PAGE->set_pagelayout('standard');
+$PAGE->navbar->add(get_string('managesubscriptions', 'calendar'));
+
+if ($courseid != SITEID && !empty($courseid)) {
+ $course = $DB->get_record('course', array('id' => $courseid));
+ $courses = array($course->id => $course);
+} else {
+ $course = get_site();
+ $courses = calendar_get_default_courses();
+}
+require_course_login($course);
+if (!calendar_user_can_add_event($course)) {
+ print_error('errorcannotimport', 'calendar');
+}
+
+$form = new calendar_addsubscription_form(null);
+$form->set_data(array(
+ 'course' => $course->id
+));
+
+$importresults = '';
+
+$formdata = $form->get_data();
+if (!empty($formdata)) {
+ require_sesskey(); // Must have sesskey for all actions.
+ $subscriptionid = calendar_add_subscription($formdata);
+ if ($formdata->importfrom == CALENDAR_IMPORT_FROM_FILE) {
+ // Blank the URL if it's a file import.
+ $formdata->url = '';
+ $calendar = $form->get_ical_data();
+ $ical = new iCalendar();
+ $ical->unserialize($calendar);
+ $importresults = calendar_import_icalendar_events($ical, $courseid, $subscriptionid);
+ } else {
+ $importresults = calendar_update_subscription_events($subscriptionid);
+ }
+ // Redirect to prevent refresh issues.
+ redirect($PAGE->url);
+} else if (!empty($subscriptionid)) {
+ // The user is wanting to perform an action upon an existing subscription.
+ require_sesskey(); // Must have sesskey for all actions.
+ $importresults = calendar_process_subscription_row($subscriptionid, $pollinterval, $action);
+}
+
+$sql = 'SELECT *
+ FROM {event_subscriptions}
+ WHERE courseid = :courseid
+ OR (courseid = 0 AND userid = :userid)';
+$params = array('courseid' => $courseid, 'userid' => $USER->id);
+$subscriptions = $DB->get_records_sql($sql, $params);
+
+// Print title and header.
+$PAGE->set_title("$course->shortname: ".get_string('calendar', 'calendar').": ".get_string('subscriptions', 'calendar'));
+$PAGE->set_heading($course->fullname);
+$PAGE->set_button(calendar_preferences_button($course));
+
+$renderer = $PAGE->get_renderer('core_calendar');
+
+echo $OUTPUT->header();
+// Display a table of subscriptions.
+echo $renderer->subscription_details($courseid, $subscriptions, $importresults);
+// Display the add subscription form.
+$form->display();
+echo $OUTPUT->footer();
\ No newline at end of file
--- /dev/null
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Allows the user to manage calendar subscriptions.
+ *
+ * @copyright 2012 Jonathan Harker
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @package calendar
+ */
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
+}
+
+require_once($CFG->libdir.'/formslib.php');
+
+/**
+ * Form for adding a subscription to a Moodle course calendar.
+ * @copyright 2012 Jonathan Harker
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class calendar_addsubscription_form extends moodleform {
+
+ /**
+ * Defines the form used to add calendar subscriptions.
+ */
+ public function definition() {
+ $mform = $this->_form;
+ $courseid = optional_param('course', 0, PARAM_INT);
+
+ $mform->addElement('header', 'addsubscriptionform', get_string('importcalendarheading', 'calendar'));
+
+ // Name.
+ $mform->addElement('text', 'name', get_string('subscriptionname', 'calendar'), array('maxsize' => '255', 'size' => '40'));
+ $mform->addRule('name', get_string('required'), 'required');
+ $mform->setType('name', PARAM_TEXT);
+
+ // Import from (url | importfile).
+ $mform->addElement('html', get_string('importfrominstructions', 'calendar'));
+ $choices = array(CALENDAR_IMPORT_FROM_FILE => get_string('importfromfile', 'calendar'),
+ CALENDAR_IMPORT_FROM_URL => get_string('importfromurl', 'calendar'));
+ $mform->addElement('select', 'importfrom', get_string('importcalendarfrom', 'calendar'), $choices);
+ $mform->setDefault('importfrom', CALENDAR_IMPORT_FROM_URL);
+
+ // URL.
+ $mform->addElement('text', 'url', get_string('importfromurl', 'calendar'), array('maxsize' => '255', 'size' => '50'));
+ $mform->setType('url', PARAM_URL);
+
+ // Import file
+ $mform->addElement('filepicker', 'importfile', get_string('importfromfile', 'calendar'));
+
+ $mform->disabledIf('url', 'importfrom', 'eq', CALENDAR_IMPORT_FROM_FILE);
+ $mform->disabledIf('importfile', 'importfrom', 'eq', CALENDAR_IMPORT_FROM_URL);
+
+ // Poll interval
+ $choices = calendar_get_pollinterval_choices();
+ $mform->addElement('select', 'pollinterval', get_string('pollinterval', 'calendar'), $choices);
+ $mform->setDefault('pollinterval', 604800);
+ $mform->addHelpButton('pollinterval', 'pollinterval', 'calendar');
+ $mform->setType('pollinterval', PARAM_INT);
+
+ // Eventtype: 0 = user, 1 = global, anything else = course ID.
+ list($choices, $groups) = calendar_get_eventtype_choices($courseid);
+ $mform->addElement('select', 'eventtype', get_string('eventkind', 'calendar'), $choices);
+ $mform->addRule('eventtype', get_string('required'), 'required');
+ $mform->setType('eventtype', PARAM_INT);
+
+ if (!empty($groups) and is_array($groups)) {
+ $groupoptions = array();
+ foreach ($groups as $group) {
+ $groupoptions[$group->id] = $group->name;
+ }
+ $mform->addElement('select', 'groupid', get_string('typegroup', 'calendar'), $groupoptions);
+ $mform->setType('groupid', PARAM_INT);
+ $mform->disabledIf('groupid', 'eventtype', 'noteq', 'group');
+ }
+
+ $mform->addElement('hidden', 'course');
+ $mform->addElement('hidden', 'sesskey', sesskey());
+ $mform->addElement('submit', 'add', get_string('add'));
+ }
+
+ /**
+ * Validates the returned data.
+ *
+ * @param array $data
+ * @param array $files
+ * @return array
+ */
+ public function validation($data, $files) {
+ $errors = parent::validation($data, $files);
+ if (empty($data['url']) && empty($data['importfile'])) {
+ if (!empty($data['importfrom']) && $data['importfrom'] == CALENDAR_IMPORT_FROM_FILE) {
+ $errors['importfile'] = get_string('errorrequiredurlorfile', 'calendar');
+ } else {
+ $errors['url'] = get_string('errorrequiredurlorfile', 'calendar');
+ }
+ }
+ return $errors;
+ }
+
+ /**
+ * Returns the ical content either from the uploaded file, or from the URL.
+ *
+ * @return bool|mixed|string
+ */
+ public function get_ical_data() {
+ $formdata = $this->get_data();
+ switch ($formdata->importfrom) {
+ case CALENDAR_IMPORT_FROM_FILE:
+ $calendar = $this->get_file_content('importfile');
+ break;
+ case CALENDAR_IMPORT_FROM_URL:
+ $calendar = download_file_content($formdata->importurl);
+ break;
+ }
+ return $calendar;
+ }
+}
\ No newline at end of file
* @package calendar
*/
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); /// It must be included from a Moodle page
+}
+
/**
* The primary renderer for the calendar.
*/
}
return $this->output->render($select);
}
+
+ /**
+ * Renders a table containing information about calendar subscriptions.
+ *
+ * @param int $courseid
+ * @param array $subscriptions
+ * @param string $importresults
+ * @return string
+ */
+ public function subscription_details($courseid, $subscriptions, $importresults = '') {
+ $table = new html_table();
+ $table->head = array(
+ get_string('colcalendar', 'calendar'),
+ get_string('collastupdated', 'calendar'),
+ get_string('colpoll', 'calendar'),
+ get_string('colactions', 'calendar')
+ );
+ $table->align = array('left', 'left', 'left', 'center');
+ $table->width = '100%';
+ $table->data = array();
+
+ if (empty($subscriptions)) {
+ $cell = new html_table_cell(get_string('nocalendarsubscriptions', 'calendar'));
+ $cell->colspan = 4;
+ $table->data[] = new html_table_row(array($cell));
+ }
+ $strnever = new lang_string('never', 'calendar');
+ foreach ($subscriptions as $sub) {
+ $label = $sub->name;
+ if (!empty($sub->url)) {
+ $label = html_writer::link($sub->url, $label);
+ }
+ if (empty($sub->lastupdated)) {
+ $lastupdated = $strnever->out();
+ } else {
+ $lastupdated = userdate($sub->lastupdated, get_string('strftimedatetimeshort', 'langconfig'));
+ }
+
+ $cell = new html_table_cell($this->subscription_action_form($sub, $courseid));
+ $cell->colspan = 2;
+
+ $table->data[] = new html_table_row(array(
+ new html_table_cell($label),
+ new html_table_cell($lastupdated),
+ $cell
+ ));
+ }
+
+ $out = $this->output->box_start('generalbox calendarsubs');
+
+ $out .= $importresults;
+ $out .= html_writer::table($table);
+ $out .= $this->output->box_end();
+ return $out;
+ }
+
+ /**
+ * Creates a form to perform actions on a given subscription.
+ *
+ * @param stdClass $subscription
+ * @param int $courseid
+ * @return string
+ */
+ protected function subscription_action_form($subscription, $courseid) {
+ // Assemble form for the subscription row.
+ $html = html_writer::start_tag('form', array('action' => new moodle_url('/calendar/managesubscriptions.php'), 'method' => 'post'));
+ if (empty($subscription->url)) {
+ // Don't update an iCal file, which has no URL.
+ $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'pollinterval', 'value' => '0'));
+ } else {
+ // Assemble pollinterval control.
+ $html .= html_writer::start_tag('div', array('style' => 'float:left;'));
+ $html .= html_writer::start_tag('select', array('name' => 'pollinterval'));
+ foreach (calendar_get_pollinterval_choices() as $k => $v) {
+ $attributes = array();
+ if ($k == $subscription->pollinterval) {
+ $attributes['selected'] = 'selected';
+ }
+ $html .= html_writer::tag('option', $v, $attributes);
+ }
+ $html .= html_writer::end_tag('select');
+ $html .= html_writer::end_tag('div');
+ }
+ $html .= html_writer::start_tag('div', array('style' => 'float:right;'));
+ $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
+ $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'course', 'value' => $courseid));
+ $html .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'id', 'value' => $subscription->id));
+ if (!empty($subscription->url)) {
+ $html .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'action', 'value' => get_string('update')));
+ }
+ $html .= html_writer::empty_tag('input', array('type' => 'submit', 'name' => 'action', 'value' => get_string('remove')));
+ $html .= html_writer::end_tag('div');
+ $html .= html_writer::end_tag('form');
+ return $html;
+ }
}
\ No newline at end of file
}
require_course_login($course);
-if (calendar_user_can_add_event($course)) {
- $importresults = calendar_process_subscription_form($courseid);
-}
-
$calendar = new calendar_information($day, $mon, $yr);
$calendar->prepare_for_view($course, $courses);
break;
}
-//Link to calendar export page
+//Link to calendar export page.
echo $OUTPUT->container_start('bottom');
-if (calendar_user_can_add_event($course)) {
- echo calendar_show_subscriptions($courseid, $importresults);
-}
if (!empty($CFG->enablecalendarexport)) {
echo $OUTPUT->single_button(new moodle_url('export.php', array('course'=>$courseid)), get_string('exportcalendar', 'calendar'));
+ if (calendar_user_can_add_event($course)) {
+ echo $OUTPUT->single_button(new moodle_url('/calendar/managesubscriptions.php', array('course'=>$courseid)), get_string('managesubscriptions', 'calendar'));
+ }
if (isloggedin()) {
$authtoken = sha1($USER->id . $USER->password . $CFG->calendar_exportsalt);
$link = new moodle_url('/calendar/export_execute.php', array('preset_what'=>'all', 'preset_time'=>'recentupcoming', 'userid' => $USER->id, 'authtoken'=>$authtoken));
echo $OUTPUT->container_end();
echo html_writer::end_tag('div');
echo $renderer->complete_layout();
-echo $OUTPUT->footer();
+echo $OUTPUT->footer();
\ No newline at end of file
$string['clickhide'] = 'click to hide';
$string['clickshow'] = 'click to show';
$string['colcalendar'] = 'Calendar';
-$string['collastupdated'] = 'Last Updated';
+$string['collastupdated'] = 'Last updated';
$string['colpoll'] = 'Poll';
$string['colactions'] = 'Actions';
$string['commontasks'] = 'Options';
$string['erroraddingevent'] = 'Failed to add event';
$string['errorbadsubscription'] = 'Calendar subscription not found.';
$string['errorbeforecoursestart'] = 'Cannot set event before course start date';
+$string['errorcannotimport'] = 'You cannot set up a calendar subscription at this time.';
$string['errorinvaliddate'] = 'Invalid date';
$string['errorinvalidminutes'] = 'Specify duration in minutes by giving a number between 1 and 999.';
$string['errorinvalidrepeats'] = 'Specify the number of events by giving a number between 1 and 99.';
+$string['errorinvalidicalurl'] = 'The given iCal URL is invalid.';
$string['errornodescription'] = 'Description is required';
$string['errornoeventname'] = 'Name is required';
$string['errorrequiredurlorfile'] = 'Either a URL or a file is required to import a calendar.';
$string['eventrepeat'] = 'Repeats';
$string['eventsall'] = 'All events';
$string['eventsdeleted'] = 'Events deleted';
-$string['eventsimported'] = 'Events imported';
-$string['eventsupdated'] = 'Events updated';
+$string['eventsimported'] = 'Events imported: {$a}';
+$string['eventsupdated'] = 'Events updated: {$a}';
$string['eventsfor'] = '{$a} events';
$string['eventskey'] = 'Events key';
$string['eventsrelatedtocourses'] = 'Events related to courses';
$string['invalidtimedurationminutes'] = 'The duration in minutes you have entered is invalid. Please enter the duration in minutes greater than 0 or select no duration.';
$string['invalidtimedurationuntil'] = 'The date and time you selected for duration until is before the start time of the event. Please correct this before proceeding.';
$string['iwanttoexport'] = 'Export';
+$string['managesubscriptions'] = 'Manage subscriptions';
$string['manyevents'] = '{$a} events';
$string['mon'] = 'Mon';
$string['monday'] = 'Monday';
$string['newevent'] = 'New event';
$string['notitle'] = 'no title';
$string['noupcomingevents'] = 'There are no upcoming events';
-$string['nocalendarsubscriptions'] = 'No calendar subscriptions.';
+$string['nocalendarsubscriptions'] = 'You have no calendar subscriptions.';
$string['oneevent'] = '1 event';
$string['pollinterval'] = 'Poll interval';
$string['pollinterval_help'] = 'How often you would like the calendar to update with new events.';
$string['showuserevents'] = 'Show user events';
$string['shown'] = 'shown';
$string['spanningevents'] = 'Events underway';
+$string['subscriptions'] = 'Subscriptions';
$string['subscriptionname'] = 'Calendar name';
+$string['subscriptionremoved'] = 'Calendar subscription {$a} removed';
+$string['subscriptionupdated'] = 'Calendar subscription {$a} updated';
$string['sun'] = 'Sun';
$string['sunday'] = 'Sunday';
$string['thu'] = 'Thu';
<?xml version="1.0" encoding="UTF-8" ?>
-<XMLDB PATH="lib/db" VERSION="20121011" COMMENT="XMLDB file for core Moodle tables"
+<XMLDB PATH="lib/db" VERSION="20121012" COMMENT="XMLDB file for core Moodle tables"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
>
<FIELD NAME="uuid" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="visible" NEXT="sequence"/>
<FIELD NAME="sequence" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="1" SEQUENCE="false" PREVIOUS="uuid" NEXT="timemodified"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="sequence" NEXT="subscriptionid"/>
- <FIELD NAME="subscriptionid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" PREVIOUS="timemodified"/>
+ <FIELD NAME="subscriptionid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="The event_subscription id this event is associated with." PREVIOUS="timemodified"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="fk_raterid" TYPE="foreign" FIELDS="raterid" REFTABLE="user" REFFIELDS="id" PREVIOUS="fk_definitionid"/>
</KEYS>
</TABLE>
- <TABLE NAME="event_subscriptions" COMMENT="Tracks subscriptions to remote calendars" PREVIOUS="grading_instances">
+ <TABLE NAME="event_subscriptions" COMMENT="Tracks subscriptions to remote calendars." PREVIOUS="grading_instances">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="url"/>
<FIELD NAME="url" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="id" NEXT="courseid"/>
<FIELD NAME="courseid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="url" NEXT="groupid"/>
<FIELD NAME="groupid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="courseid" NEXT="userid"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="groupid" NEXT="pollinterval"/>
- <FIELD NAME="pollinterval" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="userid" NEXT="lastupdated"/>
+ <FIELD NAME="pollinterval" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Frequency of checks for new/changed events" PREVIOUS="userid" NEXT="lastupdated"/>
<FIELD NAME="lastupdated" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" PREVIOUS="pollinterval" NEXT="name"/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="lastupdated"/>
</FIELDS>
if ($oldversion < 2012103000.00) {
// create new event_subscriptions table
$table = new xmldb_table('event_subscriptions');
- $table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
+ $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('url', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
$table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
$table->add_field('groupid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
$table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
$table->add_field('pollinterval', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
$table->add_field('lastupdated', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
- $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, '');
+ $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
if ($oldversion < 2012103000.01) {
// Add subscription field to the event table
$table = new xmldb_table('event');
- $field = new xmldb_field('subscriptionid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, null, null, null, 'timemodified');
+ $field = new xmldb_field('subscriptionid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'timemodified');
+
+ // Conditionally launch add field subscriptionid
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
// Fix uuid field in event table to match RFC-2445 UID property
- $field = new xmldb_field('uuid', XMLDB_TYPE_CHAR, 255, null, XMLDB_NOTNULL, null, '', 'visible');
+ $field = new xmldb_field('uuid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'visible');
if ($dbman->field_exists($table, $field)) {
+ // Changing precision of field uuid on table event to (255)
$dbman->change_field_precision($table, $field);
}
-
// Main savepoint reached
upgrade_main_savepoint(true, 2012103000.01);
}