--- /dev/null
+<?php
+
+$string['areabackup'] = 'Package archive';
+$string['areacontent'] = 'Content';
+$string['contentheader'] = 'Content';
+$string['deploymenterror'] = 'Content package error!';
+$string['keepold'] = 'Archive packages';
+$string['keepoldexplain'] = 'How many packages should be archived?';
+$string['modulename'] = 'IMS Content Package';
+$string['modulenameplural'] = 'IMS Content packages';
+$string['navigation'] = 'Navigation';
+$string['packagefile'] = 'Package file';
+$string['toc'] = 'TOC';
--- /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/>.
+
+/**
+ * Capability definitions for the imscp module.
+ *
+ * @package mod-imscp
+ * @copyright 2009 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+$mod_imscp_capabilities = array(
+
+/* TODO: review public portfolio API first!
+ 'mod/imscp:portfolioexport' => array(
+
+ 'captype' => 'read',
+ 'contextlevel' => CONTEXT_MODULE,
+ 'legacy' => array(
+ 'teacher' => CAP_ALLOW,
+ 'editingteacher' => CAP_ALLOW,
+ )
+ ),*/
+
+);
+
--- /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/>.
+
+/**
+ * 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-imscp
+ * @copyright 2009 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+function xmldb_imscp_install() {
+ global $CFG;
+
+ // Install logging support
+ update_log_display_entry('imscp', 'view', 'imscp', 'name');
+ update_log_display_entry('imscp', 'view all', 'imscp', 'name');
+ update_log_display_entry('imscp', 'update', 'imscp', 'name');
+ update_log_display_entry('imscp', 'add', 'imscp', 'name');
+
+ // Upgrade from old resource module type if needed
+ require_once("$CFG->dirroot/mod/imscp/db/upgradelib.php");
+ imscp_20_migrate();
+}
+
+function xmldb_imscp_install_recovery() {
+ global $CFG;
+
+ // Upgrade from old resource module type if needed
+ require_once("$CFG->dirroot/mod/imscp/db/upgradelib.php");
+ imscp_20_migrate();
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" ?>
+<XMLDB PATH="mod/imscp/db" VERSION="20090729" COMMENT="XMLDB file for IMS Content Package module "
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
+>
+ <TABLES>
+ <TABLE NAME="imscp" COMMENT="each record is one imscp resource">
+ <FIELDS>
+ <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="course"/>
+ <FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
+ <FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" PREVIOUS="course" NEXT="intro"/>
+ <FIELD NAME="intro" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" PREVIOUS="name" NEXT="introformat"/>
+ <FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="intro" NEXT="revision"/>
+ <FIELD NAME="revision" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="incremented when after each file changes, solves browser caching issues" PREVIOUS="introformat" NEXT="keepold"/>
+ <FIELD NAME="keepold" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="false" DEFAULT="-1" SEQUENCE="false" COMMENT="incremented when after each file changes, solves browser caching issues" PREVIOUS="revision" NEXT="structure"/>
+ <FIELD NAME="structure" TYPE="text" LENGTH="medium" NOTNULL="false" SEQUENCE="false" PREVIOUS="keepold" NEXT="timemodified"/>
+ <FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="structure"/>
+ </FIELDS>
+ <KEYS>
+ <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
+ </KEYS>
+ <INDEXES>
+ <INDEX NAME="course" UNIQUE="false" FIELDS="course"/>
+ </INDEXES>
+ </TABLE>
+ </TABLES>
+</XMLDB>
\ 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/>.
+
+/**
+ * IMS CP module upgrade code
+ *
+ * @package mod-imscp
+ * @copyright 2009 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+function xmldb_imscp_upgrade($oldversion) {
+ global $CFG, $DB;
+
+ $dbman = $DB->get_manager();
+ $result = true;
+
+
+ return $result;
+}
--- /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/>.
+
+/**
+ * IMS CP module upgrade related helper functions
+ *
+ * @package mod-imscp
+ * @copyright 2009 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Migrate imscp module data from 1.9 resource_old table to new imscp table
+ * @return void
+ */
+function imscp_20_migrate() {
+ global $CFG, $DB;
+ require_once("$CFG->libdir/filelib.php");
+ require_once("$CFG->dirroot/course/lib.php");
+ require_once("$CFG->dirroot/mod/imscp/locallib.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'=>'ims', 'migrated'=>0))) {
+ return;
+ }
+
+ $fs = get_file_storage();
+
+ foreach ($candidates as $candidate) {
+ upgrade_set_timeout(60);
+
+ $imscp = new object();
+ $imscp->course = $candidate->course;
+ $imscp->name = $candidate->name;
+ $imscp->intro = $candidate->intro;
+ $imscp->introformat = $candidate->introformat;
+ $imscp->revision = 1;
+ $imscp->keepold = 1;
+ $imscp->timemodified = time();
+
+ if (!$imscp = resource_migrate_to_module('imscp', $candidate, $imscp)) {
+ continue;
+ }
+
+ $context = get_context_instance(CONTEXT_MODULE, $candidate->cmid);
+ $root = "$CFG->dataroot/$candidate->course/$CFG->moddata/resource/$candidate->oldid";
+
+ // migrate package backup file
+ if ($candidate->reference) {
+ $package = basename($candidate->reference);
+ $fullpath = $root.'/'.$package;
+ if (file_exists($fullpath)) {
+ $file_record = array('contextid' => $context->id,
+ 'filearea' => 'imscp_backup',
+ 'itemid' => 1,
+ 'filepath' => '/',
+ 'filename' => $package);
+ $fs->create_file_from_pathname($file_record, $fullpath);
+ }
+ }
+
+ // migrate extracted package data
+ $files = imsc_migrate_get_old_files($root, '');
+ $file_record = array('contextid'=>$context->id, 'filearea'=>'imscp_content', 'itemid'=>1);
+ $error = false;
+ foreach ($files as $relname=>$fullpath) {
+ $parts = explode('/', $relname);
+ $file_record['filename'] = array_pop($parts);
+ $parts[] = ''; // keep trailing slash
+ $file_record['filepath'] = implode('/', $parts);
+
+ try {
+ $fs->create_file_from_pathname($file_record, $fullpath);
+ } catch (Exception $e) {
+ //continue on error, we can not recover anyway
+ $error = true;
+ notify("IMSCP: failed migrating file: $relname");
+ }
+ }
+ unset($files);
+
+ // parse manifest
+ $structure = imscp_parse_structure($imscp, $context);
+ $imscp->structure = is_array($structure) ? serialize($structure) : null;
+ $DB->update_record('imscp', $imscp);
+
+ // remove old moddata dir only if no error and manifest ok
+ if (!$error and is_array($structure)) {
+ fulldelete($root);
+ }
+ }
+
+ $candidates->close();
+
+ // clear all course modinfo caches
+ rebuild_course_cache(0, true);
+}
+
+/**
+ * Private function returning all extracted IMS content package file
+ */
+function imsc_migrate_get_old_files($path, $relative) {
+ $result = array();
+ $items = new DirectoryIterator($path);
+ foreach ($items as $item) {
+ if ($item->isDot() or $item->isLink()) {
+ // symbolik links could create infinite loops or cause unintended file migration, sorry
+ continue;
+ }
+ $pathname = $item->getPathname();
+ $relname = $relative.'/'.$item->getFilename();
+ if ($item->isFile()) {
+ $result[$relname] = $pathname;
+ } else if ($item->isDir()) {
+ $result = array_merge($result, imsc_migrate_get_old_files($pathname, $relname));
+ }
+ unset($item);
+ }
+ unset($items);
+ return $result;
+}
\ No newline at end of file
--- /dev/null
+// 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/>.
+
+/**
+ * Javascript helper function for IMS Content Package module including
+ * dummy SCORM API.
+ *
+ * @package mod-imscp
+ * @copyright 2009 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/** Dummy SCORM API adapter */
+var API = new function () {
+ this.LMSCommit = function (parameter) {return "true";};
+ this.LMSFinish = function (parameter) {return "true";};
+ this.LMSGetDiagnostic = function (errorCode) {return "n/a";};
+ this.LMSGetErrorString = function (errorCode) {return "n/a";};
+ this.LMSGetLastError = function () {return "0";};
+ this.LMSGetValue = function (element) {return "";};
+ this.LMSInitialize = function (parameter) {return "true";};
+ this.LMSSetValue = function (element, value) {return "true";};
+};
+
+var imscp_layout_widget;
+var imscp_current_node;
+var imscp_buttons = [];
+var imscp_bloody_labelclick = false;
+var imscp_panel;
+
+function imscp_init() {
+ YAHOO.util.Event.onDOMReady(function () {
+ imscp_setup();
+ });
+}
+
+function imscp_setup() {
+ // layout
+ YAHOO.widget.LayoutUnit.prototype.STR_COLLAPSE = mstr.moodle.hide;
+ YAHOO.widget.LayoutUnit.prototype.STR_EXPAND = mstr.moodle.show;
+
+ imscp_layout_widget = new YAHOO.widget.Layout('imscp_layout', {
+ minWidth: 600,
+ minHeight: 400,
+ units: [
+ { position: 'left', body: 'imscp_toc', header: mstr.imscp.toc, width: 250, resize: true, gutter: '2px 5px 5px 2px', collapse: true, minWidth:150},
+ { position: 'center', body: '<div id="imscp_content"></div>', gutter: '2px 5px 5px 2px', scroll: true}
+ ]
+ });
+ imscp_layout_widget.render();
+ var left = imscp_layout_widget.getUnitByPosition('left');
+ left.on('collapse', function() {
+ imscp_resize_frame();
+ });
+ left.on('expand', function() {
+ imscp_resize_frame();
+ });
+
+ // ugly resizing hack that works around problems with resizing of iframes and objects
+ left._resize.on('startResize', function() {
+ var obj = YAHOO.util.Dom.get('imscp_object');
+ obj.style.display = 'none';
+ });
+ left._resize.on('endResize', function() {
+ var obj = YAHOO.util.Dom.get('imscp_object');
+ obj.style.display = 'block';
+ imscp_resize_frame();
+ });
+
+ // TOC tree
+ var tree = new YAHOO.widget.TreeView('imscp_tree');
+ tree.singleNodeHighlight = true;
+ tree.subscribe('labelClick', function(node) {
+ imscp_activate_item(node);
+ if (node.children.length) {
+ imscp_bloody_labelclick = true;
+ }
+ });
+ tree.subscribe('collapse', function(node) {
+ if (imscp_bloody_labelclick) {
+ imscp_bloody_labelclick = false;
+ return false;
+ }
+ });
+ tree.subscribe('expand', function(node) {
+ if (imscp_bloody_labelclick) {
+ imscp_bloody_labelclick = false;
+ return false;
+ }
+ });
+ tree.expandAll();
+ tree.render();
+
+ // navigation
+ imscp_panel = new YAHOO.widget.Panel('imscp_navpanel', { visible:true, draggable:true, close:false,
+ context: ['page', 'bl', 'bl', ["windowScroll", "textResize", "windowResize"]], constraintoviewport:true} );
+ imscp_panel.setHeader(mstr.imscp.navigation);
+ //TODO: make some better&accessible buttons
+ imscp_panel.setBody('<span id="imscp_nav"><button id="nav_skipprev"><<</button><button id="nav_prev"><</button><button id="nav_up">^</button><button id="nav_next">></button><button id="nav_skipnext">>></button></span>');
+ imscp_panel.render();
+ imscp_buttons[0] = new YAHOO.widget.Button('nav_skipprev');
+ imscp_buttons[1] = new YAHOO.widget.Button('nav_prev');
+ imscp_buttons[2] = new YAHOO.widget.Button('nav_up');
+ imscp_buttons[3] = new YAHOO.widget.Button('nav_next');
+ imscp_buttons[4] = new YAHOO.widget.Button('nav_skipnext');
+ imscp_buttons[0].on('click', function(ev) {
+ imscp_activate_item(imscp_skipprev(imscp_current_node));
+ });
+ imscp_buttons[1].on('click', function(ev) {
+ imscp_activate_item(imscp_prev(imscp_current_node));
+ });
+ imscp_buttons[2].on('click', function(ev) {
+ imscp_activate_item(imscp_up(imscp_current_node));
+ });
+ imscp_buttons[3].on('click', function(ev) {
+ imscp_activate_item(imscp_next(imscp_current_node));
+ });
+ imscp_buttons[4].on('click', function(ev) {
+ imscp_activate_item(imscp_skipnext(imscp_current_node));
+ });
+ imscp_panel.render();
+
+ // finally activate the first item
+ imscp_activate_item(tree.getRoot().children[0]);
+
+ // resizing
+ imscp_resize_layout(false);
+
+ // fix layout if window resized
+ window.onresize = function() {
+ imscp_resize_layout(true);
+ };
+}
+
+
+function imscp_activate_item(node) {
+ if (!node) {
+ return;
+ }
+ imscp_current_node = node;
+ imscp_current_node.highlight();
+
+ var content = new YAHOO.util.Element('imscp_content');
+ try {
+ // first try IE way - it can not set name attribute later
+ // and also it has some restrictions on DOM access from object tag
+ var obj = document.createElement('<iframe id="imscp_object" src="'+node.href+'">');
+ } catch (e) {
+ var obj = document.createElement('object');
+ obj.setAttribute('id', 'imscp_object');
+ obj.setAttribute('type', 'text/html');
+ obj.setAttribute('data', node.href);
+ }
+ var old = YAHOO.util.Dom.get('imscp_object');
+ if (old) {
+ content.replaceChild(obj, old);
+ } else {
+ content.appendChild(obj);
+ }
+ imscp_resize_frame();
+
+ imscp_current_node.focus();
+ imscp_fixnav();
+}
+
+/**
+ * Enables/disables navigation buttons as needed.
+ * @return void
+ */
+function imscp_fixnav() {
+ imscp_buttons[0].set('disabled', (imscp_skipprev(imscp_current_node) == null));
+ imscp_buttons[1].set('disabled', (imscp_prev(imscp_current_node) == null));
+ imscp_buttons[2].set('disabled', (imscp_up(imscp_current_node) == null));
+ imscp_buttons[3].set('disabled', (imscp_next(imscp_current_node) == null));
+ imscp_buttons[4].set('disabled', (imscp_skipnext(imscp_current_node) == null));
+}
+
+
+function imscp_resize_layout(alsowidth) {
+ if (alsowidth) {
+ var layout = YAHOO.util.Dom.get('imscp_layout');
+ layout.style.width = '500px';
+ var newwidth = imscp_get_htmlelement_size('content', 'width');
+ if (newwidth > 500) {
+ layout.style.width = newwidth+'px';
+ }
+ }
+ var pageheight = imscp_get_htmlelement_size('page', 'height');
+ var layoutheight = imscp_get_htmlelement_size(imscp_layout_widget, 'height');
+ var newheight = layoutheight + parseInt(YAHOO.util.Dom.getViewportHeight()) - pageheight - 20;
+ if (newheight > 400) {
+ imscp_layout_widget.setStyle('height', newheight+'px');
+ }
+ imscp_layout_widget.render();
+ imscp_resize_frame();
+
+ imscp_panel.align('bl', 'bl');
+}
+
+function imscp_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);
+}
+
+function imscp_resize_frame() {
+ var obj = YAHOO.util.Dom.get('imscp_object');
+ if (obj) {
+ var content = imscp_layout_widget.getUnitByPosition('center').get('wrap');
+ obj.style.width = (content.offsetWidth - 6)+'px';
+ obj.style.height = (content.offsetHeight - 10)+'px';
+ }
+}
+
+
+function imscp_up(node) {
+ if (node.depth > 0) {
+ return node.parent;
+ }
+ return null;
+}
+
+function imscp_lastchild(node) {
+ if (node.children.length) {
+ return imscp_lastchild(node.children[node.children.length-1]);
+ } else {
+ return node;
+ }
+}
+
+function imscp_prev(node) {
+ if (node.previousSibling && node.previousSibling.children.length) {
+ return imscp_lastchild(node.previousSibling);
+ }
+ return imscp_skipprev(node);
+}
+
+function imscp_skipprev(node) {
+ if (node.previousSibling) {
+ return node.previousSibling;
+ } else if (node.depth > 0) {
+ return node.parent;
+ }
+ return null;
+}
+
+function imscp_next(node) {
+ if (node.children.length) {
+ return node.children[0];
+ }
+ return imscp_skipnext(node);
+}
+
+function imscp_skipnext(node) {
+ if (node.nextSibling) {
+ return node.nextSibling;
+ } else if (node.depth > 0) {
+ return imscp_skipnext(node.parent);
+ }
+ return null;
+}
+
--- /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/>.
+
+/**
+ * List of file imscps in course
+ *
+ * @package mod-imscp
+ * @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, 'imscp', 'view all', "index.php?id=$course->id", '');
+
+$strimscp = get_string('modulename', 'imscp');
+$strimscps = get_string('modulenameplural', 'imscp');
+$strweek = get_string('week');
+$strtopic = get_string('topic');
+$strname = get_string('name');
+$strintro = get_string('moduleintro');
+$strlastmodified = get_string('lastmodified');
+
+$PAGE->set_url('mod/imscp/index.php', array('id' => $course->id));
+$PAGE->set_title($course->shortname.': '.$strimscps);
+$PAGE->set_heading($course->fullname);
+$navlinks = array(array('name' => $strimscps, 'link' => '', 'type' => 'activityinstance'));
+echo $OUTPUT->header(build_navigation($navlinks), navmenu($course));
+
+if (!$imscps = get_all_instances_in_course('imscp', $course)) {
+ notice(get_string('thereareno', 'moodle', $strimscps), "$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 ($imscps as $imscp) {
+ $cm = $modinfo->cms[$imscp->coursemodule];
+ if ($course->format == 'weeks' or $course->format == 'topics') {
+ $printsection = '';
+ if ($imscp->section !== $currentsection) {
+ if ($imscp->section) {
+ $printsection = $imscp->section;
+ }
+ if ($currentsection !== '') {
+ $table->data[] = 'hr';
+ }
+ $currentsection = $imscp->section;
+ }
+ } else {
+ $printsection = '<span class="smallinfo">'.userdate($imscp->timemodified)."</span>";
+ }
+
+ $class = $imscp->visible ? '' : 'class="dimmed"'; // hidden modules are dimmed
+ $table->data[] = array (
+ $printsection,
+ "<a $class href=\"view.php?id=$cm->id\">".format_string($imscp->name)."</a>",
+ format_module_intro('imscp', $imscp, $cm->id));
+}
+
+echo $OUTPUT->table($table);
+
+echo $OUTPUT->footer();
--- /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/>.
+
+/**
+ * Mandatory public API of imscp module
+ *
+ * @package mod-imscp
+ * @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 IMS CP 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 imscp_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 imscp_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 imscp_reset_userdata($data) {
+ return array();
+}
+
+/**
+ * List of view style log actions
+ * @return array
+ */
+function imscp_get_view_actions() {
+ return array('view', 'view all');
+}
+
+/**
+ * List of update style log actions
+ * @return array
+ */
+function imscp_get_post_actions() {
+ return array('update', 'add');
+}
+
+/**
+ * Add imscp instance.
+ * @param object $data
+ * @param object $mform
+ * @return int new imscp instance id
+ */
+function imscp_add_instance($data, $mform) {
+ global $CFG, $DB;
+ require_once("$CFG->dirroot/mod/imscp/locallib.php");
+
+ $cmid = $data->coursemodule;
+
+ $data->timemodified = time();
+ $data->revision = 1;
+ $data->structure = null;
+
+ $data->id = $DB->insert_record('imscp', $data);
+
+ // we need to use context now, so we need to make sure all needed info is already in db
+ $DB->set_field('course_modules', 'instance', $data->id, array('id'=>$cmid));
+ $context = get_context_instance(CONTEXT_MODULE, $cmid);
+ $imscp = $DB->get_record('imscp', array('id'=>$data->id), '*', MUST_EXIST);
+
+ if ($filename = $mform->get_new_filename('package')) {
+ if ($package = $mform->save_stored_file('package', $context->id, 'imscp_backup', 1, '/', $filename)) {
+ // extract package content
+ $packer = get_file_packer('application/zip');
+ $package->extract_to_storage($packer, $context->id, 'imscp_content', 1, '/');
+ $structure = imscp_parse_structure($imscp, $context);
+ $imscp->structure = is_array($structure) ? serialize($structure) : null;
+ $DB->update_record('imscp', $imscp);
+ }
+ }
+
+ return $data->id;
+}
+
+/**
+ * Update imscp instance.
+ * @param object $data
+ * @param object $mform
+ * @return bool true
+ */
+function imscp_update_instance($data, $mform) {
+ global $CFG, $DB;
+ require_once("$CFG->dirroot/mod/imscp/locallib.php");
+
+ $cmid = $data->coursemodule;
+
+ $data->timemodified = time();
+ $data->id = $data->instance;
+ $imscp->structure = null; // better reparse structure after each update
+
+ $DB->update_record('imscp', $data);
+
+ $context = get_context_instance(CONTEXT_MODULE, $cmid);
+ $imscp = $DB->get_record('imscp', array('id'=>$data->id), '*', MUST_EXIST);
+
+ if ($filename = $mform->get_new_filename('package')) {
+ $fs = get_file_storage();
+
+ $imscp->revision++;
+ $DB->update_record('imscp', $imscp);
+
+ // get a list of existing packages before adding new package
+ if ($imscp->keepold > -1) {
+ $packages = $fs->get_area_files($context->id, 'imscp_backup', false, "itemid ASC", false);
+ } else {
+ $packages = array();
+ }
+
+ $package = $mform->save_stored_file('package', $context->id, 'imscp_backup', $imscp->revision, '/', $filename);
+
+ // purge all extracted content
+ $fs->delete_area_files($context->id, 'imscp_content');
+
+ // extract package content
+ if ($package) {
+ $packer = get_file_packer('application/zip');
+ $package->extract_to_storage($packer, $context->id, 'imscp_content', $imscp->revision, '/');
+ }
+
+ // cleanup old package files, keep current + keepold
+ while ($packages and (count($packages) > $imscp->keepold)) {
+ $package = array_shift($packages);
+ $fs->delete_area_files($context->id, 'imscp_backup', $package->get_itemid());
+ }
+ }
+
+ $structure = imscp_parse_structure($imscp, $context);
+ $imscp->structure = is_array($structure) ? serialize($structure) : null;
+ $DB->update_record('imscp', $imscp);
+
+ return true;
+}
+
+/**
+ * Delete imscp instance.
+ * @param int $id
+ * @return bool true
+ */
+function imscp_delete_instance($id) {
+ global $DB;
+
+ if (!$imscp = $DB->get_record('imscp', array('id'=>$id))) {
+ return false;
+ }
+
+ // note: all context files are deleted automatically
+
+ $DB->delete_records('imscp', array('id'=>$imscp->id));
+
+ return true;
+}
+
+/**
+ * Return use outline
+ * @param object $course
+ * @param object $user
+ * @param object $mod
+ * @param object $imscp
+ * @return object|null
+ */
+function imscp_user_outline($course, $user, $mod, $imscp) {
+ global $DB;
+
+ if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'imscp',
+ 'action'=>'view', 'info'=>$imscp->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 $imscp
+ */
+function imscp_user_complete($course, $user, $mod, $imscp) {
+ global $CFG, $DB;
+
+ if ($logs = $DB->get_records('log', array('userid'=>$user->id, 'module'=>'imscp',
+ 'action'=>'view', 'info'=>$imscp->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', 'imscp');
+ }
+}
+
+/**
+ * Returns the users with data in one imscp
+ *
+ * @param int $imscpid
+ * @return bool false
+ */
+function imscp_get_participants($imscpid) {
+ return false;
+}
+
+/**
+ * Lists all browsable file areas
+ * @param object $course
+ * @param object $cm
+ * @param object $context
+ * @return array
+ */
+function imscp_get_file_areas($course, $cm, $context) {
+ $areas = array();
+ if (has_capability('moodle/course:managefiles', $context)) {
+ $areas['imscp_content'] = get_string('areacontent', 'imscp');
+ $areas['imscp_backup'] = get_string('areabackup', 'imscp');
+ }
+ return $areas;
+}
+
+/**
+ * File browsing support for imscp module ontent area.
+ * @param object $browser
+ * @param object $areas
+ * @param object $course
+ * @param object $cm
+ * @param object $context
+ * @param string $filearea
+ * @param int $itemid
+ * @param string $filepath
+ * @param string $filename
+ * @return object file_info instance or null if not found
+ */
+function imscp_get_file_info($browser, $areas, $course, $cm, $context, $filearea, $itemid, $filepath, $filename) {
+ global $CFG, $DB;
+ require_once("$CFG->dirroot/mod/imscp/locallib.php");
+
+ // note: imscp_intro handled in file_browser automatically
+
+ if (!has_capability('moodle/course:managefiles', $context)) {
+ // no peaking here, sorry
+ return null;
+ }
+
+ if ($filearea !== 'imscp_content' and $filearea !== 'imscp_backup') {
+ return null;
+ }
+ if (is_null($itemid)) {
+ return new imscp_file_info($browser, $course, $cm, $context, $areas, $filearea, $itemid);
+ }
+
+ $fs = get_file_storage();
+ $filepath = is_null($filepath) ? '/' : $filepath;
+ $filename = is_null($filename) ? '.' : $filename;
+ if (!$storedfile = $fs->get_file($context->id, $filearea, $itemid, $filepath, $filename)) {
+ return null;
+ }
+
+ // do not allow manual modification of any files!
+ $urlbase = $CFG->wwwroot.'/pluginfile.php';
+ return new file_info_stored($browser, $context, $storedfile, $urlbase, $itemid, true, true, false, false);
+}
+
+/**
+ * Serves the imscp files.
+ *
+ * @param object $course
+ * @param object $cminfo
+ * @param object $context
+ * @param string $filearea
+ * @param array $args
+ * @param bool $forcedownload
+ * @return bool false if file not found, does not return if found - justsend the file
+ */
+function imscp_pluginfile($course, $cminfo, $context, $filearea, $args, $forcedownload) {
+ global $CFG, $DB;
+
+ if (!$cminfo->uservisible) {
+ return false;
+ }
+
+ if (!$cm = get_coursemodule_from_instance('imscp', $cminfo->instance, $course->id)) {
+ return false;
+ }
+
+ if ($filearea === 'imscp_content') {
+ require_course_login($course, true, $cm);
+ $revision = array_shift($args);
+ $fs = get_file_storage();
+ $relativepath = '/'.implode('/', $args);
+ if ($relativepath === '/imsmanifest.xml') {
+ if (!has_capability('moodle/course:managefiles', $context)) {
+ // no stealing of detailed package info ;-)
+ return false;
+ }
+ }
+ $fullpath = $context->id.$filearea.$revision.$relativepath;
+ if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
+ return false;
+ }
+
+ // finally send the file
+ send_stored_file($file, 86400, 0, $forcedownload);
+
+ } else if ($filearea === 'imscp_backup') {
+ require_login($course, false, $cm);
+ if (!has_capability('moodle/course:managefiles', $context)) {
+ // no stealing of package backups
+ return false;
+ }
+ $revision = array_shift($args);
+ $fs = get_file_storage();
+ $relativepath = '/'.implode('/', $args);
+ $fullpath = $context->id.$filearea.$revision.$relativepath;
+ if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
+ return false;
+ }
+
+ // finally send the file
+ send_stored_file($file, 86400, 0, $forcedownload);
+
+ } else {
+ return false;
+ }
+}
--- /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/>.
+
+/**
+ * Private imscp module utility functions
+ *
+ * @package mod-imscp
+ * @copyright 2009 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once("$CFG->dirroot/mod/imscp/lib.php");
+require_once("$CFG->libdir/file/file_browser.php");
+require_once("$CFG->libdir/filelib.php");
+require_once("$CFG->libdir/resourcelib.php");
+
+function imscp_print_content($imscp, $cm, $course) {
+ global $PAGE, $CFG;
+
+ $items = unserialize($imscp->structure);
+ $first = reset($items);
+ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+ $urlbase = "$CFG->wwwroot/pluginfile.php";
+ $path = '/'.$context->id.'/imscp_content/'.$imscp->revision.'/'.$first['href'];
+ $firsturl = file_encode_url($urlbase, $path, false);
+
+ echo '<div id="imscp_layout">';
+ echo '<div id="imscp_toc">';
+ echo '<div id="imscp_tree"><ul>';
+ foreach ($items as $item) {
+ echo imscp_htmllize_item($item, $imscp, $cm);
+ }
+ echo '</ul></div></div>';
+ echo '</div>';
+ echo '<div id="imscp_navpanel"></div>';
+
+ echo $PAGE->requires->js_function_call('imscp_init')->now();
+ return;
+}
+
+/**
+ * Internal function - creates htmls structure suitable for YUI tree.
+ */
+function imscp_htmllize_item($item, $imscp, $cm) {
+ global $CFG;
+
+ $context = get_context_instance(CONTEXT_MODULE, $cm->id);
+ $urlbase = "$CFG->wwwroot/pluginfile.php";
+ $path = '/'.$context->id.'/imscp_content/'.$imscp->revision.'/'.$item['href'];
+ $url = file_encode_url($urlbase, $path, false);
+ $result = "<li><a href=\"$url\">".$item['title'].'</a>';
+ if ($item['subitems']) {
+ $result .= '<ul>';
+ foreach ($item['subitems'] as $subitem) {
+ $result .= imscp_htmllize_item($subitem, $imscp, $cm);
+ }
+ $result .= '</ul>';
+ }
+ $result .= '</li>';
+
+ return $result;
+}
+
+function imscp_parse_structure($imscp, $context) {
+ $fs = get_file_storage();
+
+ if (!$manifestfile = $fs->get_file($context->id, 'imscp_content', $imscp->revision, '/', 'imsmanifest.xml')) {
+ return null;
+ }
+
+
+ $doc = new DOMDocument();
+ if (!$doc->loadXML($manifestfile->get_content(), LIBXML_NONET)) {
+ return null;
+ }
+
+ // we put this fake URL as base in order to detect path changes caused by xml:base attributes
+ $doc->documentURI = 'http://grrr/';
+
+ $xmlorganizations = $doc->getElementsByTagName('organizations');
+ if (empty($xmlorganizations->length)) {
+ return null;
+ }
+ $default = null;
+ if ($xmlorganizations->item(0)->attributes->getNamedItem('default')) {
+ $default = $xmlorganizations->item(0)->attributes->getNamedItem('default')->nodeValue;
+ }
+ $xmlorganization = $doc->getElementsByTagName('organization');
+ if (empty($xmlorganization->length)) {
+ return null;
+ }
+ $organization = null;
+ foreach ($xmlorganization as $org) {
+ if (is_null($organization)) {
+ // use first if default nor found
+ $organization = $org;
+ }
+ if (!$org->attributes->getNamedItem('identifier')) {
+ continue;
+ }
+ if ($default === $org->attributes->getNamedItem('identifier')->nodeValue) {
+ // found default - use it
+ $organization = $org;
+ break;
+ }
+ }
+
+ // load all resources
+ $resources = array();
+
+ $xmlresources = $doc->getElementsByTagName('resource');
+ foreach ($xmlresources as $res) {
+ if (!$identifier = $res->attributes->getNamedItem('identifier')) {
+ continue;
+ }
+ $identifier = $identifier->nodeValue;
+ if ($xmlbase = $res->baseURI) {
+ // undo the fake URL, we are interested in relative links only
+ $xmlbase = str_replace('http://grrr/', '/', $xmlbase);
+ $xmlbase = rtrim($xmlbase, '/').'/';
+ } else {
+ $xmlbase = '';
+ }
+ if (!$href = $res->attributes->getNamedItem('href')) {
+ continue;
+ }
+ $href = $href->nodeValue;
+ if (strpos($href, 'http://') !== 0) {
+ $href = $xmlbase.$href;
+ }
+ // href cleanup - Some packages are poorly done and use \ in urls
+ $href = ltrim(strtr($href, "\\", '/'), '/');
+ $resources[$identifier] = $href;
+ }
+
+ $items = array();
+ foreach ($organization->childNodes as $child) {
+ if ($child->nodeName === 'item') {
+ if (!$item = imscp_recursive_item($child, 0, $resources)) {
+ continue;
+ }
+ $items[] = $item;
+ }
+ }
+
+ return $items;
+}
+
+function imscp_recursive_item($xmlitem, $level, $resources) {
+ $identifierref = '';
+ if ($identifierref = $xmlitem->attributes->getNamedItem('identifierref')) {
+ $identifierref = $identifierref->nodeValue;
+ }
+
+ $title = '?';
+ $subitems = array();
+
+ foreach ($xmlitem->childNodes as $child) {
+ if ($child->nodeName === 'title') {
+ $title = $child->textContent;
+
+ } else if ($child->nodeName === 'item') {
+ if ($subitem = imscp_recursive_item($child, $level+1, $resources)) {
+ $subitems[] = $subitem;
+ }
+ }
+ }
+
+ return array('href' => isset($resources[$identifierref]) ? $resources[$identifierref] : '',
+ 'title' => $title,
+ 'level' => $level,
+ 'subitems' => $subitems,
+ );
+}
+
+/**
+ * File browsing support class
+ */
+class imscp_file_info extends file_info {
+ protected $course;
+ protected $cm;
+ protected $areas;
+ protected $filearea;
+
+ public function __construct($browser, $course, $cm, $context, $areas, $filearea) {
+ parent::__construct($browser, $context);
+ $this->course = $course;
+ $this->cm = $cm;
+ $this->areas = $areas;
+ $this->filearea = $filearea;
+ }
+
+ /**
+ * Returns list of standard virtual file/directory identification.
+ * The difference from stored_file parameters is that null values
+ * are allowed in all fields
+ * @return array with keys contextid, filearea, itemid, filepath and filename
+ */
+ public function get_params() {
+ return array('contextid'=>$this->context->id,
+ 'filearea' =>$this->filearea,
+ 'itemid' =>null,
+ 'filepath' =>null,
+ 'filename' =>null);
+ }
+
+ /**
+ * Returns localised visible name.
+ * @return string
+ */
+ public function get_visible_name() {
+ return $this->areas[$this->filearea];
+ }
+
+ /**
+ * Can I add new files or directories?
+ * @return bool
+ */
+ public function is_writable() {
+ return false;
+ }
+
+ /**
+ * Is directory?
+ * @return bool
+ */
+ public function is_directory() {
+ return true;
+ }
+
+ /**
+ * Returns list of children.
+ * @return array of file_info instances
+ */
+ public function get_children() {
+ global $DB;
+
+ $children = array();
+ $itemids = $DB->get_records('files', array('contextid'=>$this->context->id, 'filearea'=>$this->filearea), 'itemid', "DISTINCT itemid");
+ foreach ($itemids as $itemid=>$unused) {
+ if ($child = $this->browser->get_file_info($this->context, $this->filearea, $itemid)) {
+ $children[] = $child;
+ }
+ }
+ return $children;
+ }
+
+ /**
+ * Returns parent file_info instance
+ * @return file_info or null for root
+ */
+ public function get_parent() {
+ return $this->browser->get_file_info($this->context);
+ }
+}
--- /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/>.
+
+/**
+ * IMS CP configuration form
+ *
+ * @package mod-imscp
+ * @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/resource/locallib.php');
+require_once($CFG->libdir.'/filelib.php');
+
+class mod_imscp_mod_form extends moodleform_mod {
+ function definition() {
+ global $CFG, $DB;
+ $mform = $this->_form;
+
+ $config = get_config('imscp');
+
+ //-------------------------------------------------------
+ $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', 'imscp'));
+ $mform->addElement('static', 'note', '', '<i>(TODO: Filepicker is borked, sorry.)</i>');
+// $mform->addElement('filepicker', 'package', get_string('packagefile', 'imscp'));
+ $mform->setMaxFileSize(10000000);
+ $mform->addElement('file', 'package', get_string('packagefile', 'imscp'));
+
+ $options = array('-1'=>get_string('all'), '0'=>get_string('no'), '1'=>'1', '2'=>'2', '5'=>'5', '10'=>'10', '20'=>'20');
+ $mform->addElement('select', 'keepold', get_string('keepold', 'imscp'), $options);
+ $mform->setDefault('keepold', $config->keepold);
+ $mform->setAdvanced('keepold', $config->keepold_adv);
+
+ //-------------------------------------------------------
+ $this->standard_coursemodule_elements();
+
+ //-------------------------------------------------------
+ $this->add_action_buttons();
+ }
+
+ function validation($data, $files) {
+ global $USER;
+
+ if ($errors = parent::validation($data, $files)) {
+ return $errors;
+ }
+
+ $usercontext = get_context_instance(CONTEXT_USER, $USER->id);
+ $fs = get_file_storage();
+ /*
+ if (!$files = $fs->get_area_files($usercontext->id, 'user_draft', $data['package'], 'id', false)) {
+ if (!$this->current->instance) {
+ $errors['package'] = get_string('required');
+ return $errors;
+ }
+ }
+
+ $files = reset($file);
+
+ if ($file->get_mimetype() != 'application/zip') {
+ $errors['package'] = get_string('invalidfiletype', 'error', '', $file);
+ // better delete current file, it is not usable anyway
+ $fs->delete_area_files($usercontext->id, 'user_draft', $data['package']);
+ }*/
+
+ // TODO: filepicker borked
+ if (empty($files)) {
+ if (!$this->current->instance) {
+ $errors['package'] = get_string('required');
+ return $errors;
+ }
+ }
+
+ return $errors;
+ }
+}
--- /dev/null
+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/>.
+
+copyright 2009 Petr Skoda (http://skodak.org)
+license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+
+
+IMS CP module
+=============
+
+IMS CP module is a successor to original 'ims' type plugin of Resource module.
+
+TODO:
+ * implement portfolio support
+ * new backup/restore (Eloy)
+ * old restore support (Eloy)
+ * reimplement some repository support (Eloy)
\ 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/>.
+
+/**
+ * IMS CP module admin settings and defaults
+ *
+ * @package mod-imscp
+ * @copyright 2009 Petr Skoda (http://skodak.org)
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+if ($ADMIN->fulltree) {
+
+ //--- general settings -----------------------------------------------------------------------------------
+ $settings->add(new admin_setting_configcheckbox('imscp/requiremodintro', get_string('requiremodintro', 'admin'),
+ get_string('configrequiremodintro', 'admin'), 1));
+
+ //--- modedit defaults -----------------------------------------------------------------------------------
+ $settings->add(new admin_setting_heading('imscpmodeditdefaults', get_string('modeditdefaults', 'admin'), get_string('condifmodeditdefaults', 'admin')));
+ $options = array('-1'=>get_string('all'), '0'=>get_string('no'), '1'=>'1', '2'=>'2', '5'=>'5', '10'=>'10', '20'=>'20');
+ $settings->add(new admin_setting_configselect_with_advanced('imscp/keepold',
+ get_string('keepold', 'imscp'), get_string('keepoldexplain', 'imscp'),
+ array('value'=>1, 'adv'=>false), $options));
+}
--- /dev/null
+/*** Modules: IMS CP ***/
+
+/* TODO: yui styling has to go here because the order of CSS loading is not solved yet */
+
+#mod-imscp-view #imscp_nav {
+ text-align: center;
+ margin-bottom: 5px;
+ margin-top: 5px;
+}
+
+#mod-imscp-view #imscp_toc .ygtv-highlight1 {
+ font-weight: bold;
+}
+
+#mod-imscp-view #footer {
+ display:none;
+}
+
+/* this is a temporary hack until we solve theYUI CSS trouble */
+#mod-imscp-view .yui-layout-hd {
+ background-image: none;
+ height:3em;
+ background-color: #DDDDDD;
+}
+
+#mod-imscp-view .yui-layout-hd h2 {
+ color: black;
+}
\ 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/>.
+
+/**
+ * IMS CP module version information
+ *
+ * @package mod-imscp
+ * @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;
+
--- /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/>.
+
+/**
+ * IMS CP module main user interface
+ *
+ * @package mod-imscp
+ * @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/imscp/locallib.php");
+
+$id = optional_param('id', 0, PARAM_INT); // Course module ID
+$i = optional_param('i', 0, PARAM_INT); // IMS CP instance id
+
+if ($i) { // Two ways to specify the module
+ $imscp = $DB->get_record('imscp', array('id'=>$i), '*', MUST_EXIST);
+ $cm = get_coursemodule_from_instance('imscp', $imscp->id, $imscp->course, false, MUST_EXIST);
+
+} else {
+ $cm = get_coursemodule_from_id('imscp', $id, 0, false, MUST_EXIST);
+ $imscp = $DB->get_record('imscp', 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, 'imscp', 'view', 'view.php?id='.$cm->id, $imscp->id, $cm->id);
+
+$PAGE->set_url('mod/imscp/view.php', array('id' => $cm->id));
+$PAGE->requires->yui_lib('json')->in_head();
+$PAGE->requires->yui_lib('event')->in_head();
+$PAGE->requires->yui_lib('treeview')->in_head();
+$PAGE->requires->yui_lib('layout')->in_head();
+$PAGE->requires->yui_lib('button')->in_head();
+$PAGE->requires->yui_lib('container')->in_head();
+$PAGE->requires->yui_lib('dragdrop')->in_head();
+$PAGE->requires->yui_lib('resize')->in_head();
+$PAGE->requires->js('mod/imscp/functions.js')->in_head();
+$PAGE->requires->css('mod/imscp/style.css');
+
+$PAGE->requires->string_for_js('navigation', 'imscp');
+$PAGE->requires->string_for_js('toc', 'imscp');
+$PAGE->requires->string_for_js('hide', 'moodle');
+$PAGE->requires->string_for_js('show', 'moodle');
+
+// TODO: ugly hack for a page layout without footer and blocks
+$PAGE->set_generaltype('topframe');
+
+$PAGE->set_title($course->shortname.': '.$imscp->name);
+$PAGE->set_heading($course->fullname);
+$PAGE->set_activity_record($imscp);
+$PAGE->set_button(update_module_button($cm->id, '', get_string('modulename', 'imscp')));
+echo $OUTPUT->header(build_navigation('', $cm), navmenu($course, $cm));
+
+// verify imsmanifest was parsed properly
+if (!$imscp->structure) {
+ echo $OUTPUT->notification(get_string('deploymenterror', 'imscp'), 'notifyproblem');
+ echo $OUTPUT->footer();
+ die;
+}
+
+imscp_print_content($imscp, $cm, $course);
+
+echo $OUTPUT->footer();