From: skodak Date: Thu, 13 Aug 2009 20:49:37 +0000 (+0000) Subject: MDL-20069 new URL module, includes migrate from old mod/resource; remaining issues... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=58a27a7467ef4d562a15525d8dcb8c8889b81bf9;p=moodle.git MDL-20069 new URL module, includes migrate from old mod/resource; remaining issues to be listed in tracker as sub-tasks --- diff --git a/lang/en_utf8/url.php b/lang/en_utf8/url.php new file mode 100644 index 0000000000..48f76ff5a7 --- /dev/null +++ b/lang/en_utf8/url.php @@ -0,0 +1,35 @@ +. + +/** + * Capability definitions for the url module. + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$mod_url_capabilities = array( +/* TODO: review public portfolio API first! + 'mod/url:portfolioexport' => array( + + 'captype' => 'read', + 'contextlevel' => CONTEXT_MODULE, + 'legacy' => array( + 'teacher' => CAP_ALLOW, + 'editingteacher' => CAP_ALLOW, + ) + ),*/ + +); + diff --git a/mod/url/db/install.php b/mod/url/db/install.php new file mode 100644 index 0000000000..61aa3f3eac --- /dev/null +++ b/mod/url/db/install.php @@ -0,0 +1,57 @@ +. + +/** + * Post installation and migration code. + * + * This file replaces: + * - STATEMENTS section in db/install.xml + * - lib.php/modulename_install() post installation hook + * - partially defaults.php + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +function xmldb_url_install() { + global $CFG; + + // Install logging support + update_log_display_entry('url', 'view', 'url', 'name'); + update_log_display_entry('url', 'view all', 'url', 'name'); + update_log_display_entry('url', 'update', 'url', 'name'); + update_log_display_entry('url', 'add', 'url', 'name'); + + // migrate settings if present + if (!empty($CFG->resource_secretphrase)) { + set_config('secretphrase', $CFG->resource_secretphrase, 'url'); + } + unset_config('resource_secretphrase'); + + // Upgrade from old resource module type if needed + require_once("$CFG->dirroot/mod/url/db/upgradelib.php"); + url_20_migrate(); +} + +function xmldb_url_install_recovery() { + global $CFG; + + // Upgrade from old resource module type if needed + require_once("$CFG->dirroot/mod/url/db/upgradelib.php"); + url_20_migrate(); +} diff --git a/mod/url/db/install.xml b/mod/url/db/install.xml new file mode 100644 index 0000000000..eb8f4d2f4c --- /dev/null +++ b/mod/url/db/install.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/mod/url/db/upgrade.php b/mod/url/db/upgrade.php new file mode 100644 index 0000000000..e4c0f72e31 --- /dev/null +++ b/mod/url/db/upgrade.php @@ -0,0 +1,54 @@ +. + +/** + * URL module upgrade code + * + * This file keeps track of upgrades to + * the resource module + * + * Sometimes, changes between versions involve + * alterations to database structures and other + * major things that may break installations. + * + * The upgrade function in this file will attempt + * to perform all the necessary actions to upgrade + * your older installtion to the current version. + * + * If there's something it cannot do itself, it + * will tell you what you need to do. + * + * The commands in here will all be database-neutral, + * using the methods of database_manager class + * + * Please do not forget to use upgrade_set_timeout() + * before any action that may take longer time to finish. + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +function xmldb_url_upgrade($oldversion) { + global $CFG, $DB; + + $dbman = $DB->get_manager(); + $result = true; + + + return $result; +} diff --git a/mod/url/db/upgradelib.php b/mod/url/db/upgradelib.php new file mode 100644 index 0000000000..47629a9987 --- /dev/null +++ b/mod/url/db/upgradelib.php @@ -0,0 +1,128 @@ +. + +/** + * URL module upgrade related helper functions + * + * @package url-resource + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Migrate url module data from 1.9 resource_old table to new url table + * @return void + */ +function url_20_migrate() { + global $CFG, $DB; + + require_once("$CFG->libdir/filelib.php"); + require_once("$CFG->libdir/resourcelib.php"); + require_once("$CFG->dirroot/course/lib.php"); + + if (!file_exists("$CFG->dirroot/mod/resource/db/upgradelib.php")) { + // bad luck, somebody deleted resource module + return; + } + + require_once("$CFG->dirroot/mod/resource/db/upgradelib.php"); + + // create resource_old table and copy resource table there if needed + if (!resource_20_prepare_migration()) { + // no modules or fresh install + return; + } + + if (!$candidates = $DB->get_recordset('resource_old', array('type'=>'file', 'migrated'=>0))) { + return; + } + $fs = get_file_storage(); + + foreach ($candidates as $candidate) { + $path = $candidate->reference; + $siteid = get_site()->id; + + if (strpos($path, 'LOCALPATH') === 0) { + // ignore not maintained local files - sorry + continue; + } else if (!strpos($path, '://')) { + // not URL + return; + } else if (preg_match("|$CFG->wwwroot/file.php(\?file=)?/$siteid(/[^\s'\"&\?#]+)|", $path, $matches)) { + // handled by resource module + return; + } else if (preg_match("|$CFG->wwwroot/file.php(\?file=)?/$candidate->course(/[^\s'\"&\?#]+)|", $path, $matches)) { + // handled by resource module + return; + } + + upgrade_set_timeout(); + + $url = new object(); + $url->course = $candidate->course; + $url->name = $candidate->name; + $url->intro = $candidate->intro; + $url->introformat = $candidate->introformat; + $url->externalurl = $path; + $url->timemodified = time(); + + $options = array('printheading'=>0, 'printintro'=>1); + $parameters = array(); + if ($candidate->options == 'frame') { + $url->display = RESOURCELIB_DISPLAY_FRAME; + + } else if ($candidate->options == 'objectframe') { + $url->display = RESOURCELIB_DISPLAY_EMBED; + + } else if ($candidate->popup) { + $url->display = RESOURCELIB_DISPLAY_POPUP; + if ($candidate->popup) { + $rawoptions = explode(',', $candidate->popup); + foreach ($rawoptions as $rawoption) { + list($name, $value) = explode('=', trim($rawoption), 2); + if ($value > 0 and ($name == 'width' or $name == 'height')) { + $options['popup'.$name] = $value; + continue; + } + } + } + + } else { + $url->display = RESOURCELIB_DISPLAY_AUTO; + } + $url->displayoptions = serialize($options); + + if ($candidate->alltext) { + $rawoptions = explode(',', $candidate->alltext); + foreach ($rawoptions as $rawoption) { + list($variable, $parameter) = explode('=', trim($rawoption), 2); + $parameters[$parameter] = $variable; + } + } + + $url->parameters = serialize($parameters); + + if (!$url = resource_migrate_to_module('url', $candidate, $url)) { + continue; + } + } + + $candidates->close(); + + // clear all course modinfo caches + rebuild_course_cache(0, true); +} \ No newline at end of file diff --git a/mod/url/functions.js b/mod/url/functions.js new file mode 100644 index 0000000000..78320c8b99 --- /dev/null +++ b/mod/url/functions.js @@ -0,0 +1,69 @@ +// 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 . + +/** + * Javascript helper function for URL module + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +function url_init_object() { + YAHOO.util.Event.onDOMReady(function () { + imscp_setup_object(); + }); +} + +function imscp_setup_object() { + url_resize_object(); + + // fix layout if window resized too + window.onresize = function() { + url_resize_object(); + }; +} + +function url_resize_object() { + var obj = YAHOO.util.Dom.get('resourceobject'); + obj.style.width = '0px'; + obj.style.height = '0px'; + var newwidth = url_get_htmlelement_size('content', 'width') - 15; + if (newwidth > 600) { + obj.style.width = newwidth + 'px'; + } else { + obj.style.width = '600px'; + } + var pageheight = url_get_htmlelement_size('page', 'height'); + var objheight = url_get_htmlelement_size(obj, 'height'); + var newheight = objheight + parseInt(YAHOO.util.Dom.getViewportHeight()) - pageheight - 30; + if (newheight > 400) { + obj.style.height = newheight + 'px'; + } else { + obj.style.height = '400px'; + } +} + + +function url_get_htmlelement_size(el, prop) { + var val = YAHOO.util.Dom.getStyle(el, prop); + if (val == 'auto') { + if (el.get) { + el = el.get('element'); // get real HTMLElement from YUI element + } + val = YAHOO.util.Dom.getComputedStyle(YAHOO.util.Dom.get(el), prop); + } + return parseInt(val); +} diff --git a/mod/url/icon.gif b/mod/url/icon.gif new file mode 100644 index 0000000000..547358b953 Binary files /dev/null and b/mod/url/icon.gif differ diff --git a/mod/url/index.php b/mod/url/index.php new file mode 100644 index 0000000000..2dc080c280 --- /dev/null +++ b/mod/url/index.php @@ -0,0 +1,104 @@ +. + +/** + * List of urls in course + * + * @package mod-url + * @copyright 2009 onwards Martin Dougiamas (http://dougiamas.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require('../../config.php'); + +$id = required_param('id', PARAM_INT); // course id + +$course = $DB->get_record('course', array('id'=>$id), '*', MUST_EXIST); + +require_course_login($course, true); + +add_to_log($course->id, 'url', 'view all', "index.php?id=$course->id", ''); + +$strurl = get_string('modulename', 'url'); +$strurls = get_string('modulenameplural', 'url'); +$strweek = get_string('week'); +$strtopic = get_string('topic'); +$strname = get_string('name'); +$strintro = get_string('moduleintro'); +$strlastmodified = get_string('lastmodified'); + +$PAGE->set_url('mod/url/index.php', array('id' => $course->id)); +$PAGE->set_title($course->shortname.': '.$strurls); +$PAGE->set_heading($course->fullname); +$navlinks = array(array('name' => $strurls, 'link' => '', 'type' => 'activityinstance')); +echo $OUTPUT->header(build_navigation($navlinks), navmenu($course)); + +if (!$urls = get_all_instances_in_course('url', $course)) { + notice(get_string('thereareno', 'moodle', $strurls), "$CFG->wwwroot/course/view.php?id=$course->id"); + exit; +} + +$table = new html_table(); +$table->set_classes(array('generaltable', 'mod_index')); + +if ($course->format == 'weeks') { + $table->head = array ($strweek, $strname, $strintro); + $table->align = array ('center', 'left', 'left'); +} else if ($course->format == 'topics') { + $table->head = array ($strtopic, $strname, $strintro); + $table->align = array ('center', 'left', 'left'); +} else { + $table->head = array ($strlastmodified, $strname, $strintro); + $table->align = array ('left', 'left', 'left'); +} + +$modinfo = get_fast_modinfo($course); +$currentsection = ''; +foreach ($urls as $url) { + $cm = $modinfo->cms[$url->coursemodule]; + if ($course->format == 'weeks' or $course->format == 'topics') { + $printsection = ''; + if ($url->section !== $currentsection) { + if ($url->section) { + $printsection = $url->section; + } + if ($currentsection !== '') { + $table->data[] = 'hr'; + } + $currentsection = $url->section; + } + } else { + $printsection = ''.userdate($url->timemodified).""; + } + + $extra = empty($cm->extra) ? '' : $cm->extra; + $icon = ''; + if (!empty($cm->icon)) { + // each url has an icon in 2.0 + $icon = ' '; + } + + $class = $url->visible ? '' : 'class="dimmed"'; // hidden modules are dimmed + $table->data[] = array ( + $printsection, + "id\">".$icon.format_string($url->name)."", + format_module_intro('url', $url, $cm->id)); +} + +echo $OUTPUT->table($table); + +echo $OUTPUT->footer(); diff --git a/mod/url/lib.php b/mod/url/lib.php new file mode 100644 index 0000000000..304903fa9e --- /dev/null +++ b/mod/url/lib.php @@ -0,0 +1,288 @@ +. + +/** + * Mandatory public API of url module + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * List of features supported in URL module + * @param string $feature FEATURE_xx constant for requested feature + * @return mixed True if module supports feature, false if not, null if doesn't know + */ +function url_supports($feature) { + switch($feature) { + case FEATURE_MOD_ARCHETYPE: return MOD_ARCHETYPE_RESOURCE; + case FEATURE_GROUPS: return false; + case FEATURE_GROUPINGS: return false; + case FEATURE_GROUPMEMBERSONLY: return true; + case FEATURE_MOD_INTRO: return true; + case FEATURE_COMPLETION_TRACKS_VIEWS: return true; + case FEATURE_GRADE_HAS_GRADE: return false; + case FEATURE_GRADE_OUTCOMES: return false; + + default: return null; + } +} + +/** + * Returns all other caps used in module + * @return array + */ +function url_get_extra_capabilities() { + return array('moodle/site:accessallgroups'); +} + +/** + * This function is used by the reset_course_userdata function in moodlelib. + * @param $data the data submitted from the reset course. + * @return array status array + */ +function url_reset_userdata($data) { + return array(); +} + +/** + * List of view style log actions + * @return array + */ +function url_get_view_actions() { + return array('view', 'view all'); +} + +/** + * List of update style log actions + * @return array + */ +function url_get_post_actions() { + return array('update', 'add'); +} + +/** + * Add url instance. + * @param object $data + * @param object $mform + * @return int new url instance id + */ +function url_add_instance($data, $mform) { + global $DB; + + $parameters = array(); + for ($i=0; $i < 100; $i++) { + $parameter = "parameter_$i"; + $variable = "variable_$i"; + if (empty($data->$parameter) or empty($data->$variable)) { + continue; + } + $parameters[$data->$parameter] = $data->$variable; + } + $data->parameters = serialize($parameters); + + $displayoptions = array(); + if ($data->display == RESOURCELIB_DISPLAY_POPUP) { + $displayoptions['popupwidth'] = $data->popupwidth; + $displayoptions['popupheight'] = $data->popupheight; + } + if (in_array($data->display, array(RESOURCELIB_DISPLAY_AUTO, RESOURCELIB_DISPLAY_EMBED, RESOURCELIB_DISPLAY_FRAME))) { + $displayoptions['printheading'] = (int)!empty($data->printheading); + $displayoptions['printintro'] = (int)!empty($data->printintro); + } + $data->displayoptions = serialize($displayoptions); + + if (strpos($data->externalurl, '://') === false) { + $data->externalurl = 'http://'.$data->externalurl; + } + + $data->timemodified = time(); + $data->id = $DB->insert_record('url', $data); + + return $data->id; +} + +/** + * Update url instance. + * @param object $data + * @param object $mform + * @return bool true + */ +function url_update_instance($data, $mform) { + global $CFG, $DB; + + $parameters = array(); + for ($i=0; $i < 100; $i++) { + $parameter = "parameter_$i"; + $variable = "variable_$i"; + if (empty($data->$parameter) or empty($data->$variable)) { + continue; + } + $parameters[$data->$parameter] = $data->$variable; + } + $data->parameters = serialize($parameters); + + $displayoptions = array(); + if ($data->display == RESOURCELIB_DISPLAY_POPUP) { + $displayoptions['popupwidth'] = $data->popupwidth; + $displayoptions['popupheight'] = $data->popupheight; + } + if (in_array($data->display, array(RESOURCELIB_DISPLAY_AUTO, RESOURCELIB_DISPLAY_EMBED, RESOURCELIB_DISPLAY_FRAME))) { + $displayoptions['printheading'] = (int)!empty($data->printheading); + $displayoptions['printintro'] = (int)!empty($data->printintro); + } + $data->displayoptions = serialize($displayoptions); + + if (strpos($data->externalurl, '://') === false) { + $data->externalurl = 'http://'.$data->externalurl; + } + + $data->timemodified = time(); + $data->id = $data->instance; + + $DB->update_record('url', $data); + + return true; +} + +/** + * Delete url instance. + * @param int $id + * @return bool true + */ +function url_delete_instance($id) { + global $DB; + + if (!$url = $DB->get_record('url', array('id'=>$id))) { + return false; + } + + // note: all context files are deleted automatically + + $DB->delete_records('url', array('id'=>$url->id)); + + return true; +} + +/** + * Return use outline + * @param object $course + * @param object $user + * @param object $mod + * @param object $url + * @return object|null + */ +function url_user_outline($course, $user, $mod, $url) { + global $DB; + + if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'url', + 'action'=>'view', 'info'=>$url->id), 'time ASC')) { + + $numviews = count($logs); + $lastlog = array_pop($logs); + + $result = new object(); + $result->info = get_string('numviews', '', $numviews); + $result->time = $lastlog->time; + + return $result; + } + return NULL; +} + +/** + * Return use complete + * @param object $course + * @param object $user + * @param object $mod + * @param object $url + */ +function url_user_complete($course, $user, $mod, $url) { + global $CFG, $DB; + + if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'url', + 'action'=>'view', 'info'=>$url->id), 'time ASC')) { + $numviews = count($logs); + $lastlog = array_pop($logs); + + $strmostrecently = get_string('mostrecently'); + $strnumviews = get_string('numviews', '', $numviews); + + echo "$strnumviews - $strmostrecently ".userdate($lastlog->time); + + } else { + print_string('neverseen', 'url'); + } +} + +/** + * Returns the users with data in one url + * + * @param int $urlid + * @return bool false + */ +function url_get_participants($urlid) { + return false; +} + +/** + * Given a course_module object, this function returns any + * "extra" information that may be needed when printing + * this activity in a course listing. + * + * See {@link get_array_of_activities()} in course/lib.php + * + * @param object $coursemodule + * @return object info + */ +function url_get_coursemodule_info($coursemodule) { + global $CFG, $DB; + require_once("$CFG->dirroot/mod/url/locallib.php"); + + if (!$url = $DB->get_record('url', array('id'=>$coursemodule->instance), 'id, name, display, displayoptions, externalurl, parameters')) { + return NULL; + } + + $info = new object(); + $info->name = $url->name; + + //note: there should be a way to differentiate links from normal resources + $info->icon = url_guess_icon($url->externalurl); + + $display = url_get_final_display_type($url); + + if ($display == RESOURCELIB_DISPLAY_POPUP) { + $fullurl = "$CFG->wwwroot/mod/url/view.php?id=$coursemodule->id&redirect=1"; + $options = empty($url->displayoptions) ? array() : unserialize($url->displayoptions); + $width = empty($options['popupwidth']) ? 620 : $options['popupwidth']; + $height = empty($options['popupheight']) ? 450 : $options['popupheight']; + $wh = "width=$width,height=$height,toolbar=no,location=no,menubar=no,copyhistory=no,status=no,directories=no,scrollbars=yes,resizable=yes"; + $info->extra = urlencode("onclick=\"window.open('$fullurl', '', '$wh'); return false;\""); + + } else if ($display == RESOURCELIB_DISPLAY_NEW) { + $fullurl = "$CFG->wwwroot/mod/url/view.php?id=$coursemodule->id&redirect=1"; + $info->extra = urlencode("onclick=\"window.open('$fullurl'); return false;\""); + + } else if ($display == RESOURCELIB_DISPLAY_OPEN) { + $fullurl = "$CFG->wwwroot/mod/url/view.php?id=$coursemodule->id&redirect=1"; + $info->extra = urlencode("onclick=\"window.location.href ='$fullurl';return false;\""); + } + + return $info; +} + diff --git a/mod/url/locallib.php b/mod/url/locallib.php new file mode 100644 index 0000000000..cfaf9c1256 --- /dev/null +++ b/mod/url/locallib.php @@ -0,0 +1,503 @@ +. + +/** + * Private url module utility functions + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once("$CFG->libdir/file/file_browser.php"); +require_once("$CFG->libdir/filelib.php"); +require_once("$CFG->libdir/resourcelib.php"); +require_once("$CFG->dirroot/mod/url/lib.php"); + +/** + * Return full url with all extra parameters + * @param string $url + * @param object $cm + * @param object $course + * @return string url + */ +function url_get_full_url($url, $cm, $course, $config=null) { + + $parameters = empty($url->parameters) ? array() : unserialize($url->parameters); + + if (empty($parameters)) { + // easy - no params + return $url->externalurl; + } + + if (!$config) { + $config = get_config('url'); + } + $paramvalues = url_get_variable_values($url, $cm, $course, $config); + + foreach ($parameters as $parse=>$parameter) { + if (isset($paramvalues[$parameter])) { + $parameters[$parse] = urlencode($parse).'='.urlencode($paramvalues[$parameter]); + } else { + unset($parameters[$parse]); + } + } + + if (empty($parameters)) { + // easy - no params available + return $url->externalurl; + } + + if (stripos($url->externalurl, 'teamspeak://') === 0) { + return $url->externalurl.'?'.implode('?', $parameters); + } else { + $join = (strpos($url->externalurl, '?') === false) ? '?' : '&'; + return $url->externalurl.$join.implode('&', $parameters); + } +} + +/** + * Print url header. + * @param object $url + * @param object $cm + * @param object $course + * @return void + */ +function url_print_header($url, $cm, $course) { + global $PAGE, $OUTPUT; + + $PAGE->set_title($course->shortname.': '.$url->name); + $PAGE->set_heading($course->fullname); + $PAGE->set_activity_record($url); + $PAGE->set_button(update_module_button($cm->id, '', get_string('modulename', 'url'))); + echo $OUTPUT->header(build_navigation('', $cm), navmenu($course, $cm)); +} + +/** + * Print url heading. + * @param object $url + * @param object $cm + * @param object $course + * @param bool $ignoresettings print even if not specified in modedit + * @return void + */ +function url_print_heading($url, $cm, $course, $ignoresettings=false) { + global $OUTPUT; + + $options = empty($url->displayoptions) ? array() : unserialize($url->displayoptions); + + if ($ignoresettings or !empty($options['printheading'])) { + echo $OUTPUT->heading(format_string($url->name), 2, 'main', 'urlheading'); + } +} + +/** + * Print url introduction. + * @param object $url + * @param object $cm + * @param object $course + * @param bool $ignoresettings print even if not specified in modedit + * @return void + */ +function url_print_intro($url, $cm, $course, $ignoresettings=false) { + global $OUTPUT; + + $options = empty($url->displayoptions) ? array() : unserialize($url->displayoptions); + if ($ignoresettings or !empty($options['printintro'])) { + if (trim(strip_tags($url->intro))) { + echo $OUTPUT->box_start('mod_introbox', 'urlintro'); + echo format_module_intro('url', $url, $cm->id); + echo $OUTPUT->box_end(); + } + } +} + +/** + * Display url frames. + * @param object $url + * @param object $cm + * @param object $course + * @return does not return + */ +function url_display_frame($url, $cm, $course) { + global $PAGE, $OUTPUT, $CFG; + + $frame = optional_param('frameset', 'main', PARAM_ALPHA); + + if ($frame === 'top') { + $PAGE->set_generaltype('topframe'); + url_print_header($url, $cm, $course); + url_print_heading($url, $cm, $course); + url_print_intro($url, $cm, $course); + echo $OUTPUT->footer(); + die; + + } else { + $config = get_config('url'); + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + $exteurl = s(url_get_full_url($url, $cm, $course, $config)); + $navurl = "$CFG->wwwroot/mod/url/view.php?id=$cm->id&frameset=top"; + $title = strip_tags(format_string($course->shortname.': '.$url->name)); + $framesize = $config->framesize; + $modulename = s(get_string('modulename','url')); + $dir = get_string('thisdirection'); + + $extframe = << + + + + $title + + + + + + +EOF; + + @header('Content-Type: text/html; charset=utf-8'); + echo $extframe; + die; + } +} + +/** + * Print url info and link. + * @param object $url + * @param object $cm + * @param object $course + * @return does not return + */ +function url_print_workaround($url, $cm, $course) { + global $OUTPUT; + + url_print_header($url, $cm, $course); + url_print_heading($url, $cm, $course, true); + url_print_intro($url, $cm, $course, true); + + $fullurl = url_get_full_url($url, $cm, $course); + + $display = url_get_final_display_type($url); + if ($display == RESOURCELIB_DISPLAY_POPUP) { + $options = empty($url->displayoptions) ? array() : unserialize($url->displayoptions); + $width = empty($options['popupwidth']) ? 620 : $options['popupwidth']; + $height = empty($options['popupheight']) ? 450 : $options['popupheight']; + $wh = "width=$width,height=$height,toolbar=no,location=no,menubar=no,copyhistory=no,status=no,directories=no,scrollbars=yes,resizable=yes"; + $extra = "onclick=\"window.open('$fullurl', '', '$wh'); return false;\""; + + } else if ($display == RESOURCELIB_DISPLAY_NEW) { + $extra = "onclick=\"this.target='_blank';\""; + + } else { + $extra = ''; + } + + echo '
'; + print_string('clicktoopen', 'url', "$fullurl"); + echo '
'; + + echo $OUTPUT->footer(); + die; +} + +/** + * Display embedded url file. + * @param object $url + * @param object $cm + * @param object $course + * @param stored_file $file main file + * @return does not return + */ +function url_display_embed($url, $cm, $course) { + global $CFG, $PAGE; + + $clicktoopen = get_string('clicktoopen', 'url', $url->externalurl); + + $mimetype = resourcelib_guess_url_mimetype($url->externalurl); + $fullurl = url_get_full_url($url, $cm, $course); + $title = $url->name; + + if (in_array($mimetype, array('image/gif','image/jpeg','image/png'))) { // It's an image + $code = resourcelib_embed_image($fullurl, $title); + + } else if ($mimetype == 'audio/mp3') { + // MP3 audio file + $code = resourcelib_embed_mp3($fullurl, $title, $clicktoopen); + + } else if ($mimetype == 'video/x-flv') { + // Flash video file + $code = resourcelib_embed_flashvideo($fullurl, $title, $clicktoopen); + + } else if ($mimetype == 'application/x-shockwave-flash') { + // Flash file + $code = resourcelib_embed_flash($fullurl, $title, $clicktoopen); + + } else if (substr($mimetype, 0, 10) == 'video/x-ms') { + // Windows Media Player file + $code = resourcelib_embed_mediaplayer($fullurl, $title, $clicktoopen); + + } else if ($mimetype == 'video/quicktime') { + // Quicktime file + $code = resourcelib_embed_quicktime($fullurl, $title, $clicktoopen); + + } else if ($mimetype == 'video/mpeg') { + // Mpeg file + $code = resourcelib_embed_mpeg($fullurl, $title, $clicktoopen); + + } else if ($mimetype == 'audio/x-pn-realaudio') { + // RealMedia file + $code = resourcelib_embed_real($fullurl, $title, $clicktoopen); + + } else { + // anything else - just try object tag enlarged as much as possible + $code = resourcelib_embed_general($fullurl, $title, $clicktoopen, $mimetype); + $PAGE->requires->yui_lib('dom')->in_head(); + $PAGE->requires->js('mod/url/functions.js')->in_head(); + $PAGE->requires->js_function_call('url_init_object'); + } + + url_print_header($url, $cm, $course); + url_print_heading($url, $cm, $course); + + echo $code; + + url_print_intro($url, $cm, $course); + + print_footer(); + die; +} + +/** + * Decide the best diaply format. + * @param object $url + * @return int display type constant + */ +function url_get_final_display_type($url) { + global $CFG; + + if ($url->display != RESOURCELIB_DISPLAY_AUTO) { + return $url->display; + } + + // detect links to local moodle pages + if (strpos($url->externalurl, $CFG->wwwroot) === 0) { + if (strpos($url->externalurl, 'file.php') === false and strpos($url->externalurl, '.php') !== false ) { + // most probably our moodle page with navigation + return RESOURCELIB_DISPLAY_OPEN; + } + } + + static $download = array('application/zip', 'application/x-tar', 'application/g-zip', // binary formats + 'application/pdf', 'text/html'); // these are known to cause trouble for external links, sorry + static $embed = array('image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', // images + 'application/x-shockwave-flash', 'video/x-flv', 'video/x-ms-wm', // video formats + 'video/quicktime', 'video/mpeg', + 'audio/mp3', 'audio/x-realaudio-plugin', 'x-realaudio-plugin', // audio formats, + ); + + $mimetype = mimeinfo('type', $url->externalurl); + + if (in_array($mimetype, $download)) { + return RESOURCELIB_DISPLAY_DOWNLOAD; + } + if (in_array($mimetype, $embed)) { + return RESOURCELIB_DISPLAY_EMBED; + } + + // let the browser deal with it somehow + return RESOURCELIB_DISPLAY_OPEN; +} + +/** + * Get the parameters that may be appended to URL + * @param object $config url module config options + * @return array array describing opt groups + */ +function url_get_variable_options($config) { + global $CFG; + + $options = array(); + $options[''] = array('' => get_string('chooseavariable', 'url')); + + $options[get_string('course')] = array( + 'courseid' => 'id', + 'coursefullname' => get_string('fullnamecourse'), + 'courseshortname' => get_string('shortnamecourse'), + 'courseidnumber' => get_string('idnumbercourse'), + 'coursesummary' => get_string('summary'), + 'courseformat' => get_string('format'), + ); + + $options[get_string('modulename', 'url')] = array( + 'urlinstance' => 'id', + 'urlcmid' => 'cmid', + 'urlname' => get_string('name'), + 'urlidnumber' => get_string('idnumbermod'), + ); + + $options[get_string('miscellaneous')] = array( + 'sitename' => get_string('fullsitename'), + 'serverurl' => get_string('serverurl', 'resource', (object)array('wwwroot'=>$CFG->wwwroot)), + 'currenttime' => get_string('time'), + 'lang' => get_string('language'), + ); + if (!empty($config->secretphrase)) { + $options[get_string('miscellaneous')]['encryptedcode'] = get_string('encryptedcode'); + } + + $options[get_string('user')] = array( + 'userid' => 'id', + 'userusername' => get_string('username'), + 'useridnumber' => get_string('idnumber'), + 'userfirstname' => get_string('firstname'), + 'userlastname' => get_string('lastname'), + 'userfullname' => get_string('fullnameuser'), + 'useremail' => get_string('email'), + 'usericq' => get_string('icqnumber'), + 'userphone1' => get_string('phone').' 1', + 'userphone2' => get_string('phone2').' 2', + 'userinstitution' => get_string('institution'), + 'userdepartment' => get_string('department'), + 'useraddress' => get_string('address'), + 'usercity' => get_string('city'), + 'usertimezone' => get_string('timezone'), + 'userurl' => get_string('webpage'), + ); + + if ($config->rolesinparams) { + $roles = get_all_roles(); + $roleoptions = array(); + foreach ($roles as $role) { + $roleoptions['course'.$role->shortname] = get_string('yourwordforx', '', $role->name); + } + $options[get_string('roles')] = $roleoptions; + } + + return $options; +} + +/** + * Get the parameter values that may be appended to URL + * @param object $url module instance + * @param object $cm + * @param object $course + * @param object $config module config options + * @return array of parameter values + */ +function url_get_variable_values($url, $cm, $course, $config) { + global $USER, $CFG; + + $site = get_site(); + + $values = array ( + 'courseid' => $course->id, + 'coursefullname' => format_string($course->fullname), + 'courseshortname' => $course->shortname, + 'courseidnumber' => $course->idnumber, + 'coursesummary' => $course->summary, + 'courseformat' => $course->format, + 'lang' => current_language(), + 'sitename' => format_string($site->fullname), + 'serverurl' => $CFG->wwwroot, + 'currenttime' => time(), + 'urlinstance' => $url->id, + 'urlcmid' => $cm->id, + 'urlname' => format_string($url->name), + 'urlidnumber' => $cm->idnumber, + ); + + if (!empty($USER->id)) { + $values['userid'] = $USER->id; + $values['userusername'] = $USER->username; + $values['useridnumber'] = $USER->idnumber; + $values['userfirstname'] = $USER->firstname; + $values['userlastname'] = $USER->lastname; + $values['userfullname'] = fullname($USER); + $values['useremail'] = $USER->email; + $values['usericq'] = $USER->icq; + $values['userphone1'] = $USER->phone1; + $values['userphone2'] = $USER->phone2; + $values['userinstitution'] = $USER->institution; + $values['userdepartment'] = $USER->department; + $values['useraddress'] = $USER->address; + $values['usercity'] = $USER->city; + $values['usertimezone'] = get_user_timezone_offset(); + $values['userurl'] = $USER->url; + } + + // weak imitation of Single-Sign-On, for backwards compatibility only + // NOTE: login hack is not included in 2.0 any more, new contrib auth plugin + // needs to be createed if somebody needs the old functionality! + if (!empty($config->secretphrase)) { + $values['encryptedcode'] = url_get_encrypted_parameter($url, $config); + } + + //hmm, this is pretty fragile and slow, why do we need it here?? + if ($config->rolesinparams) { + $roles = get_all_roles(); + $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); + $roles = role_fix_names($roles, $coursecontext, ROLENAME_ALIAS); + foreach ($roles as $role) { + $values['course'.$role->shortname] = $role->localname; + } + } + + return $values; +} + +/** + * BC internal function + * @param object $url + * @param object $config + * @return string + */ +function url_get_encrypted_parameter($url, $config) { + global $CFG; + + if (file_exists("$CFG->dirroot/local/externserverfile.php")) { + require_once("$CFG->dirroot/local/externserverfile.php"); + if (function_exists('extern_server_file')) { + return extern_server_file($url, $config); + } + } + return md5(getremoteaddr().$config->secretphrase); +} + +/** + * Optimised mimetype detection from general URL + * @param $fullurl + * @return string mimetype + */ +function url_guess_icon($fullurl) { + global $CFG; + require_once("$CFG->libdir/filelib.php"); + + if (substr_count($fullurl, '/') < 3 or substr($fullurl, -1) === '/') { + // most probably default directory - index.php, index.html, etc. + return 'f/web'; + } + + $icon = mimeinfo('icon', $fullurl); + $icon = 'f/'.str_replace(array('.gif', '.png'), '', $icon); + + if ($icon === 'f/html' or $icon === 'f/unknown') { + $icon = 'f/web'; + } + + return $icon; +} diff --git a/mod/url/mod_form.php b/mod/url/mod_form.php new file mode 100644 index 0000000000..b5fe33275d --- /dev/null +++ b/mod/url/mod_form.php @@ -0,0 +1,164 @@ +. + +/** + * URL configuration form + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once ($CFG->dirroot.'/course/moodleform_mod.php'); +require_once($CFG->dirroot.'/mod/url/locallib.php'); + +class mod_url_mod_form extends moodleform_mod { + function definition() { + global $CFG, $DB; + $mform = $this->_form; + + $config = get_config('url'); + + //------------------------------------------------------- + $mform->addElement('header', 'general', get_string('general', 'form')); + $mform->addElement('text', 'name', get_string('name'), array('size'=>'48')); + if (!empty($CFG->formatstringstriptags)) { + $mform->setType('name', PARAM_TEXT); + } else { + $mform->setType('name', PARAM_CLEAN); + } + $mform->addRule('name', null, 'required', null, 'client'); + $this->add_intro_editor($config->requiremodintro); + + //------------------------------------------------------- + $mform->addElement('header', 'content', get_string('contentheader', 'url')); + + $mform->addElement('text', 'externalurl', get_string('externalurl', 'url'), array('size'=>'100')); + + //------------------------------------------------------- + $mform->addElement('header', 'optionssection', get_string('optionsheader', 'url')); + + if ($this->current->instance) { + $options = resourcelib_get_displayoptions(explode(',', $config->displayoptions), $this->current->display); + } else { + $options = resourcelib_get_displayoptions(explode(',', $config->displayoptions)); + } + if (count($options) == 1) { + $mform->addElement('hidden', 'display'); + reset($options); + $mform->setDefault('display', key($options)); + } else { + $mform->addElement('select', 'display', get_string('displayselect', 'url'), $options); + $mform->setDefault('display', $config->display); + $mform->setAdvanced('display', $config->display_adv); + } + + if (array_key_exists(RESOURCELIB_DISPLAY_POPUP, $options)) { + $mform->addElement('text', 'popupwidth', get_string('popupwidth', 'url'), array('size'=>3)); + if (count($options) > 1) { + $mform->disabledIf('popupwidth', 'display', 'noteq', RESOURCELIB_DISPLAY_POPUP); + } + $mform->setType('popupwidth', PARAM_INT); + $mform->setDefault('popupwidth', $config->popupwidth); + $mform->setAdvanced('popupwidth', $config->popupwidth_adv); + + $mform->addElement('text', 'popupheight', get_string('popupheight', 'url'), array('size'=>3)); + if (count($options) > 1) { + $mform->disabledIf('popupheight', 'display', 'noteq', RESOURCELIB_DISPLAY_POPUP); + } + $mform->setType('popupheight', PARAM_INT); + $mform->setDefault('popupheight', $config->popupheight); + $mform->setAdvanced('popupheight', $config->popupheight_adv); + } + + if (array_key_exists(RESOURCELIB_DISPLAY_AUTO, $options) or + array_key_exists(RESOURCELIB_DISPLAY_EMBED, $options) or + array_key_exists(RESOURCELIB_DISPLAY_FRAME, $options)) { + $mform->addElement('checkbox', 'printheading', get_string('printheading', 'url')); + $mform->disabledIf('printheading', 'display', 'eq', RESOURCELIB_DISPLAY_POPUP); + $mform->disabledIf('printheading', 'display', 'eq', RESOURCELIB_DISPLAY_OPEN); + $mform->disabledIf('printheading', 'display', 'eq', RESOURCELIB_DISPLAY_NEW); + $mform->setDefault('printheading', $config->printheading); + $mform->setAdvanced('printheading', $config->printheading_adv); + + $mform->addElement('checkbox', 'printintro', get_string('printintro', 'url')); + $mform->disabledIf('printintro', 'display', 'eq', RESOURCELIB_DISPLAY_POPUP); + $mform->disabledIf('printintro', 'display', 'eq', RESOURCELIB_DISPLAY_OPEN); + $mform->disabledIf('printintro', 'display', 'eq', RESOURCELIB_DISPLAY_NEW); + $mform->setDefault('printintro', $config->printintro); + $mform->setAdvanced('printintro', $config->printintro_adv); + } + + //------------------------------------------------------- + $mform->addElement('header', 'parameterssection', get_string('parametersheader', 'url')); + + + if (empty($this->current->parameters)) { + $parcount = 5; + } else { + $parcount = 5 + count(unserialize($this->current->parameters)); + $parcount = ($parcount > 100) ? 100 : $parcount; + } + $options = url_get_variable_options($config); + + for ($i=0; $i < $parcount; $i++) { + $parameter = "parameter_$i"; + $variable = "variable_$i"; + $pargroup = "pargoup_$i"; + $group = array( + $mform->createElement('text', $parameter, '', array('size'=>'12')), + $mform->createElement('selectgroups', $variable, '', $options), + ); + $mform->addGroup($group, $pargroup, get_string('parameterinfo', 'url'), ' ', false); + $mform->setAdvanced($pargroup); + } + + //------------------------------------------------------- + $this->standard_coursemodule_elements(); + + //------------------------------------------------------- + $this->add_action_buttons(); + } + + function data_preprocessing(&$default_values) { + if (!empty($default_values['displayoptions'])) { + $displayoptions = unserialize($default_values['displayoptions']); + if (isset($displayoptions['printintro'])) { + $default_values['printintro'] = $displayoptions['printintro']; + } + if (isset($displayoptions['printheading'])) { + $default_values['printheading'] = $displayoptions['printheading']; + } + if (!empty($displayoptions['popupwidth'])) { + $default_values['popupwidth'] = $displayoptions['popupwidth']; + } + if (!empty($displayoptions['popupheight'])) { + $default_values['popupheight'] = $displayoptions['popupheight']; + } + } + if (!empty($default_values['parameters'])) { + $parameters = unserialize($default_values['parameters']); + $i = 0; + foreach ($parameters as $parameter=>$variable) { + $default_values['parameter_'.$i] = $parameter; + $default_values['variable_'.$i] = $variable; + $i++; + } + } + } + +} diff --git a/mod/url/readme.txt b/mod/url/readme.txt new file mode 100644 index 0000000000..96254e650d --- /dev/null +++ b/mod/url/readme.txt @@ -0,0 +1,29 @@ +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 . + +copyright 2009 Petr Skoda (http://skodak.org) +license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + + +URL module +============= + +URL module is one of the successors to original 'file' type plugin of Resource module. + + +TODO: + * reimplement portfolio support (?) + * new backup/restore (Eloy) + * old restore support (Eloy) diff --git a/mod/url/settings.php b/mod/url/settings.php new file mode 100644 index 0000000000..81704bf362 --- /dev/null +++ b/mod/url/settings.php @@ -0,0 +1,73 @@ +. + +/** + * Url module admin settings and defaults + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +if ($ADMIN->fulltree) { + require_once("$CFG->libdir/resourcelib.php"); + + $displayoptions = resourcelib_get_displayoptions(array(RESOURCELIB_DISPLAY_AUTO, + RESOURCELIB_DISPLAY_EMBED, + RESOURCELIB_DISPLAY_FRAME, + RESOURCELIB_DISPLAY_OPEN, + RESOURCELIB_DISPLAY_NEW, + RESOURCELIB_DISPLAY_POPUP, + )); + $defaultdisplayoptions = array(RESOURCELIB_DISPLAY_AUTO, + RESOURCELIB_DISPLAY_EMBED, + RESOURCELIB_DISPLAY_OPEN, + RESOURCELIB_DISPLAY_POPUP, + ); + + //--- general settings ----------------------------------------------------------------------------------- + $settings->add(new admin_setting_configtext('url/framesize', + get_string('framesize', 'url'), get_string('configframesize', 'url'), 130, PARAM_INT)); + $settings->add(new admin_setting_configcheckbox('url/requiremodintro', + get_string('requiremodintro', 'admin'), get_string('configrequiremodintro', 'admin'), 1)); + $settings->add(new admin_setting_configpasswordunmask('secretphrase', get_string('password'), + get_string('configsecretphrase', 'url'), '')); + $settings->add(new admin_setting_configcheckbox('url/rolesinparams', + get_string('rolesinparams', 'url'), get_string('configrolesinparams', 'url'), false)); + $settings->add(new admin_setting_configmultiselect('url/displayoptions', + get_string('displayoptions', 'url'), get_string('configdisplayoptions', 'url'), + $defaultdisplayoptions, $displayoptions)); + + //--- modedit defaults ----------------------------------------------------------------------------------- + $settings->add(new admin_setting_heading('urlmodeditdefaults', get_string('modeditdefaults', 'admin'), get_string('condifmodeditdefaults', 'admin'))); + + $settings->add(new admin_setting_configcheckbox_with_advanced('url/printheading', + get_string('printheading', 'url'), get_string('printheadingexplain', 'url'), + array('value'=>0, 'adv'=>false))); + $settings->add(new admin_setting_configcheckbox_with_advanced('url/printintro', + get_string('printintro', 'url'), get_string('printintroexplain', 'url'), + array('value'=>1, 'adv'=>false))); + $settings->add(new admin_setting_configselect_with_advanced('url/display', + get_string('displayselect', 'url'), get_string('displayselectexplain', 'url'), + array('value'=>RESOURCELIB_DISPLAY_AUTO, 'adv'=>false), $displayoptions)); + $settings->add(new admin_setting_configtext_with_advanced('url/popupwidth', + get_string('popupwidth', 'url'), get_string('popupwidthexplain', 'url'), + array('value'=>620, 'adv'=>true), PARAM_INT, 7)); + $settings->add(new admin_setting_configtext_with_advanced('url/popupheight', + get_string('popupheight', 'url'), get_string('popupheightexplain', 'url'), + array('value'=>450, 'adv'=>true), PARAM_INT, 7)); +} diff --git a/mod/url/version.php b/mod/url/version.php new file mode 100644 index 0000000000..3d26b002ab --- /dev/null +++ b/mod/url/version.php @@ -0,0 +1,29 @@ +. + +/** + * Folder module version information + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +$module->version = 2009080500; +$module->requires = 2009073101; // Requires this Moodle version +$module->cron = 0; + diff --git a/mod/url/view.php b/mod/url/view.php new file mode 100644 index 0000000000..476a2d8274 --- /dev/null +++ b/mod/url/view.php @@ -0,0 +1,68 @@ +. + +/** + * URL module main user interface + * + * @package mod-url + * @copyright 2009 Petr Skoda (http://skodak.org) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require('../../config.php'); +require_once("$CFG->dirroot/mod/url/locallib.php"); + +$id = optional_param('id', 0, PARAM_INT); // Course module ID +$u = optional_param('u', 0, PARAM_INT); // URL instance id +$redirect = optional_param('redirect', 0, PARAM_BOOL); + +if ($u) { // Two ways to specify the module + $url = $DB->get_record('url', array('id'=>$u), '*', MUST_EXIST); + $cm = get_coursemodule_from_instance('url', $url->id, $url->course, false, MUST_EXIST); + +} else { + $cm = get_coursemodule_from_id('url', $id, 0, false, MUST_EXIST); + $url = $DB->get_record('url', array('id'=>$cm->instance), '*', MUST_EXIST); +} + +$course = $DB->get_record('course', array('id'=>$cm->course), '*', MUST_EXIST); + +require_course_login($course, true, $cm); +$context = get_context_instance(CONTEXT_MODULE, $cm->id); + +add_to_log($course->id, 'url', 'view', 'view.php?id='.$cm->id, $url->id, $cm->id); + +$PAGE->set_url('mod/url/view.php', array('id' => $cm->id)); + +if ($redirect) { + // coming from course page or url index page, + // the redirection is needed for completion tracking and logging + $fullurl = url_get_full_url($url, $cm, $course); + redirect($fullurl); +} + +switch (url_get_final_display_type($url)) { + case RESOURCELIB_DISPLAY_EMBED: + url_display_embed($url, $cm, $course); + break; + case RESOURCELIB_DISPLAY_FRAME: + url_display_frame($url, $cm, $course); + break; + default: + url_print_workaround($url, $cm, $course); + break; +}