MDL-20067 new IMS Content package module, includes migrate from old mod/resource; remaining issues to be listed in tracker as sub-tasks
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
<?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';
|
||||
@@ -0,0 +1,40 @@
|
||||
<?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,
|
||||
)
|
||||
),*/
|
||||
|
||||
);
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?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();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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>
|
||||
@@ -0,0 +1,34 @@
|
||||
<?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;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<?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;
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 596 B |
@@ -0,0 +1,97 @@
|
||||
<?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();
|
||||
@@ -0,0 +1,375 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -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 <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)
|
||||
@@ -0,0 +1,38 @@
|
||||
<?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));
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*** 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;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?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;
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<?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();
|
||||
Reference in New Issue
Block a user