ÿØÿà JFIF    ÿÛ „  ( %!1"%)+...383-7(-.+  -%%--------+------------/----------------------------ÿÀ  ¶" ÿÄ     ÿÄ @    !1AQaq‘¡"±ÁÑð2’BRráS‚ñ3b¢CT²Ò #cÿÄ    ÿÄ '   1!AQ2a"‘±#ÿÚ   ? ò(/p‘—–¢·,M|¯G»R£üešT. ôŸEoCFñ‡ 4ÔkåóxR|µÁ¨ÓDà!Ç´µ˜‡p ÍQ‹§!þž^õWsŒy  åÁ§$á«%ºq˜™JyyË0y«^Ϗ -3ÃÏËÈ£Æ\P’ä„s&•‹Üs üô'àWt¹pñCp$bÚF`·7.^)¾!)ÒÙ˜–ÅÏš^h¾ø³·ìe±ŒaeÖ—Í,e=B}Jéߦ$$½—šÙÜCC¯¶è8β–Åkèwx LÉngT±æ¹£Ócœ¿Í/©Éÿ ‰ÚCÒ­mq;Tt¶–}0"zÖPcd1š­¤tˆ„ÐÓâqú[™öUCŠ2޿د­É(¸ßúçšmW,Ò ºf‹Ån™ÄLêÁ8üÁkÁ€L¥ÍuJ1œôrÂSŒÓöt!7EUíïb)AËi¬â-ÙHk8òÁiXYwÅ)O^"ÇØriÛô{»wRUKÙÏÚlÓ¬€‚’שT ] ªb—ÊîKC^×M“xùäñz¬zJ× {4[¹M'IÆeH1LCWÕ]œûº WDæà°OÅ‚¹c²ÞuA–rL`HšpCez‡V’— Ž‚Ë„–ñ­'µR0ÕÖ=À:±G»C\nÆÉ5*¢ †3šhQ4ýÒi$Õ1"Ü]¢p-q3zcQ$ªö¨¥æf›‘»´ÝÚHá„e²JÇ–iÊ:·à¬Øc5Åk»Laª*wi [0Ówk ¦a¦0Õ²ÅÅ‚T¸’³q:Æ<¹ú Ò˜Æ}2VE•Ѐp¡Ô3Úº …h³^LJºçì¥Ánó|˜ÖˆÎˆ+« ¦dø‘Mº–d\ªDðÛ„Ì×LÝ——Ð9Ç|•FèçVm™¨€™3õS–9Äå¢<̉Ìm¢±`·º˜&Z²ž Ë®D«¶»6™‰©­HÈ Àá«h­i³04æ’hxœi3ï¨(ÓL·†‹¶ËpŒ ƒÜÒ? :õdsÀ –3æÓ·Üjâ¬9—]8n¼&]I F£¼…ì–—Œ0v°LǐÅfÛ2TÖ’aµ˜N@ÖBSÏ^à´4-±°b×nÈÈœÆD=KdŒø…ÄÈK,›ÖR§fjü$^ÔÎ!„6^ s:Üun\ôkCÞò÷<—Lúl Í›G¹ÀPá¼Nc¡šÒ…ÙWͳœ±vÊáЄ×9‹P‰cEØ‘™›µŸP<×g1 º©Ø¬wiÁ^l5× I/';Ë+´Z‡ÓÄFÕp[Èð’ HÄ ó 9¬Dl4“é±Ï”V=^Hð;žLädÉa‚°Ë,#/Ž~²BÔÛ QãñQtIeórVB,ÏÂf‹4#Μc‹É3ZIÖ Œ¢¥·üxa‡Ãçè„jŠ[5 Ä!U?,3žÎ×…ðdÓ÷háŠA‰ìÄ4÷ÃÜZÃE{‰®+W\ZÍE[‰»µk»MÝ­`¢©†˜ÃV‹-f¢¡†¢a«eŠ%«Y¨©q%jâd,Ôq`) ¤¦…šˆ ¦E>0Ùb²t–Ÿ  ÷jsςҒKÈcø(é›;k(’#ôŒQ ™C> õ³M9óºÆµ¤çâ;uÀ)5>RÔ¸fÓ~Ȧ—’-$fe«"FâUˆÊwµPÏu w+"åÉó¨6s™Û9(À¨ù©hE°½†n`m~“@©›p!Vkhµ Á1šbEqqÊ@ºèl›2 –Yã%‘‚hÛ{a¶‡ÅÞM²¬çL34®Çl]®‹ŽØŒm'RÜe35æöˆ­Á­ cP9šeÁköo´L³Ì=p8]”‡B¶,šº|ɏdzXˆØk*ÇÚ{#ñ‰pã(€¶‡9ý'šÜ³½¯kƒ†Â’ëSOƒ•Å®H6+a¢µˆ‹Y¨b˜b+XˆÖ!°u!¢"µˆˆn2ˆ Å0Ä`Å Ô®c(ÓÜGº•Ä»Œ âWî%q.áÐÄ÷î%umÍ£+ÜQ,Vn¦-GphU¸¢X­&,Gt ·K¢ÅÅ·¥RÄÊÉbKn N­R2g$VµÕó Qr#–ÓZUÏð0ÎtÙÀœz ëöo“Îk¯n„T°"SÞ+³/…€½"ižãO%Í%&Δâ‘ËØ´IˆÓ°Ë‰ÞM3.™yçÁzit›`4C`k¢¼á!álÄï sÂ[×!¤l¾æo"ƒIÔ'@ªu)3›ô®“@Z à¾] üœ'‡4¸PÞkÁ-qÄH‰ÓÍBd´ÿ —¹°ÄA&ÊUC„öz‚‚RæŠtf¬>˜ÑidšEçÑL÷áý¡V±h§­c¿¥¨ƒ@g¼…Ýö^ÞËc.ž„æ“I[ ª+·zÐÒÚ,½Ð»¶€C›7jk$๖€Ž¾ÅÙpp¶ÍþéΤ ½ØÎŒq ñpæžÅ¥#Øâ49ÃÂK^MYV“,¶Éz_òæ:…;Õ«¦I3âJ£¤û5$7Èxün\â]Êe¯(Ÿ&Ž‹¶2<6Ćf× æ¢ƱqWı[(ÙÂŽç‚T7¨@ÈÉÍß‚ïÙ"&3TYlGށ†)†#5ŠA©^T2ÆÁ†)©†©†¤yGXÁ†©"†)©¼ÅV WS†#©]R–r‹q5ÕbâWþBh¯u+ªÅÄ×ü„nÑ^êkªÁj‰jeœWˆÕÕ`µDµ2Ì+Ä µDµµ5Ô{¤Þ0RF’H÷AÛ<ÊÁ§ ƈæ0Ñ£ê4 öÚµ[¬/1²€â<-¬šö²r×0o×w ´xÐÒË„ g01¬„åEM蛇Ã\6µE›‘fÙO k÷CºnÓ1`iîÒ² áÂ!ÑLÄÿ ³¬\õ*:M=Ç»c‹2[‰ØsÕLò\ŒK L^™üÄN\¶#» Ç\……ßïIœÉ$¸ÎñÍ®ÔHÇ Ûí/´>Li”„†g^$ 7NÍÑÑ2M2ªNg=k½Ð}Ÿl6‡ —JWˆ”ÞéT·+µ¦üÂFè¢Vs6ýÆ4»2+2IÝ9ô9®ÇGÙÇ1+Ä8;*Õ§ž½D*îÑWÚçá3Ma¤·ˆ¥t}š²Ü…Q+Æüµ8HíS”üxGéÁˆ¦Ël„éÈ 5 µÄƒ6äÜ(kIš¯S†fÖ&¸®×v|Äyˆ*禌Éù@7-®Ä[]ÎÖ¿ê`º…=:…žJVnݳvðÖKE¼‚ »mà ÷f®:Ë ™–4rð¡4` ܹçž~‹C=œ…¾Ïj|VDtK.ƒ"9 Ï ­–éXá³6WÒïIL-Ї Ç styles.css000064400000000721152265517310006610 0ustar00/*** Modules: IMS CP ***/ #page-mod-imscp-view #imscp_nav { text-align: center; margin-bottom: 5px; margin-top: 10px; } #page-mod-imscp-view #imscp_toc .ygtv-highlight1 { font-weight: bold; } #page-mod-imscp-view .yui-layout-hd { background-image: none; background-color: #ddd; } #page-mod-imscp-view .yui-layout-hd h2 { color: black; } .path-mod-imscp #imscp_child_list { margin-left: 1em; width: auto; height: auto; } db/services.php000064400000003601152265517310007474 0ustar00. /** * IMSCP external functions and service definitions. * * @package mod_imscp * @category external * @copyright 2015 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ defined('MOODLE_INTERNAL') || die; $functions = array( 'mod_imscp_view_imscp' => array( 'classname' => 'mod_imscp_external', 'methodname' => 'view_imscp', 'description' => 'Simulate the view.php web interface imscp: trigger events, completion, etc...', 'type' => 'write', 'capabilities' => 'mod/imscp:view', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), 'mod_imscp_get_imscps_by_courses' => array( 'classname' => 'mod_imscp_external', 'methodname' => 'get_imscps_by_courses', 'description' => 'Returns a list of IMSCP instances in a provided set of courses, if no courses are provided then all the IMSCP instances the user has access to will be returned.', 'type' => 'read', 'capabilities' => 'mod/imscp:view', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), ); db/install.php000064400000002244152265517310007321 0ustar00. /** * 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 {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Stub for database installation. */ function xmldb_imscp_install() { global $CFG; } db/log.php000064400000002456152265517310006441 0ustar00. /** * Definition of log events * * @package mod_imscp * @category log * @copyright 2010 Petr Skoda (http://skodak.org) * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $logs = array( array('module' => 'imscp', 'action' => 'view', 'mtable' => 'imscp', 'field' => 'name'), array('module' => 'imscp', 'action' => 'view all', 'mtable' => 'imscp', 'field' => 'name'), array('module' => 'imscp', 'action' => 'update', 'mtable' => 'imscp', 'field' => 'name'), array('module' => 'imscp', 'action' => 'add', 'mtable' => 'imscp', 'field' => 'name'), ); db/access.php000064400000003431152265517310007113 0ustar00. /** * Capability definitions for the imscp module. * * @package mod_imscp * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $capabilities = array( 'mod/imscp:view' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => array( 'guest' => CAP_ALLOW, 'user' => CAP_ALLOW, ) ), 'mod/imscp:addinstance' => array( 'riskbitmask' => RISK_XSS, 'captype' => 'write', 'contextlevel' => CONTEXT_COURSE, 'archetypes' => array( 'editingteacher' => CAP_ALLOW, 'manager' => CAP_ALLOW ), 'clonepermissionsfrom' => 'moodle/course:manageactivities' ), /* TODO: review public portfolio API first! 'mod/imscp:portfolioexport' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_MODULE, 'archetypes' => array( 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, ) ),*/ ); db/upgrade.php000064400000003043152265517310007300 0ustar00. /** * IMS CP module upgrade code * * @package mod_imscp * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** * Stub for database upgrade. * @param int $oldversion */ function xmldb_imscp_upgrade($oldversion) { // Automatically generated Moodle v4.2.0 release upgrade line. // Put any upgrade step following this. // Automatically generated Moodle v4.3.0 release upgrade line. // Put any upgrade step following this. // Automatically generated Moodle v4.4.0 release upgrade line. // Put any upgrade step following this. // Automatically generated Moodle v4.5.0 release upgrade line. // Put any upgrade step following this. // Automatically generated Moodle v5.0.0 release upgrade line. // Put any upgrade step following this. return true; } db/install.xml000064400000003050152265517310007326 0ustar00
lang/en/imscp.php000064400000007140152265517310007724 0ustar00. /** * Strings for component 'imscp', language 'en', branch 'MOODLE_20_STABLE' * * @package mod_imscp * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ $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['indicator:cognitivedepth'] = 'IMS pkg cognitive'; $string['indicator:cognitivedepth_help'] = 'This indicator is based on the cognitive depth reached by the student in an IMS content package resource.'; $string['indicator:cognitivedepthdef'] = 'IMS pkg cognitive'; $string['indicator:cognitivedepthdef_help'] = 'The participant has reached this percentage of the cognitive engagement offered by the IMS Package resources during this analysis interval (Levels = No view, View)'; $string['indicator:cognitivedepthdef_link'] = 'Learning_analytics_indicators#Cognitive_depth'; $string['indicator:socialbreadth'] = 'IMS pkg social'; $string['indicator:socialbreadth_help'] = 'This indicator is based on the social breadth reached by the student in an IMS content package resource.'; $string['indicator:socialbreadthdef'] = 'IMS pkg social'; $string['indicator:socialbreadthdef_help'] = 'The participant has reached this percentage of the social engagement offered by the IMS Package resources during this analysis interval (Levels = No participation, Participant alone)'; $string['indicator:socialbreadthdef_link'] = 'Learning_analytics_indicators#Social_breadth'; $string['imscp:addinstance'] = 'Add a new IMS content package'; $string['imscp:view'] = 'View IMS content'; $string['modulename'] = 'IMS content package'; $string['modulename_help'] = 'An IMS content package is a collection of files which are packaged according to an agreed standard so they can be reused in different systems. The IMS content package module enables such content packages to be uploaded as a zip file and added to a course as a resource. Content is usually displayed over several pages, with navigation between the pages. There are various options for displaying content in a pop-up window, with a navigation menu or buttons etc. An IMS content package may be used for presenting multimedia content and animations.'; $string['modulename_link'] = 'mod/imscp/view'; $string['modulenameplural'] = 'IMS content packages'; $string['navigation'] = 'Navigation'; $string['page-mod-imscp-x'] = 'Any IMS content package module page'; $string['packagefile'] = 'Package file'; $string['pluginadministration'] = 'IMSCP administration'; $string['pluginname'] = 'IMS content package'; $string['privacy:metadata'] = 'The IMS content package plugin does not store any personal data.'; $string['search:activity'] = 'IMS content package - resource information'; $string['toc'] = 'TOC'; backup/moodle2/restore_imscp_activity_task.class.php000064400000007466152265517310017027 0ustar00. /** * Defines restore_imscp_activity_task class * * @package mod_imscp * @subpackage backup-moodle2 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/imscp/backup/moodle2/restore_imscp_stepslib.php'); /** * Provides the settings and steps to perform one complete restore of the activity * * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class restore_imscp_activity_task extends restore_activity_task { /** * Define (add) particular settings this activity can have */ protected function define_my_settings() { // No particular settings for this activity. } /** * Define (add) particular steps this activity can have */ protected function define_my_steps() { // Module imscp only has one structure step. $this->add_step(new restore_imscp_activity_structure_step('imscp_structure', 'imscp.xml')); } /** * Define the contents in the activity that must be * processed by the link decoder */ public static function define_decode_contents() { $contents = array(); $contents[] = new restore_decode_content('imscp', array('intro'), 'imscp'); return $contents; } /** * Define the decoding rules for links belonging * to the activity to be executed by the link decoder */ public static function define_decode_rules() { $rules = array(); $rules[] = new restore_decode_rule('IMSCPVIEWBYID', '/mod/imscp/view.php?id=$1', 'course_module'); $rules[] = new restore_decode_rule('IMSCPINDEX', '/mod/imscp/index.php?id=$1', 'course'); return $rules; } /** * Define the restore log rules that will be applied * by the {@link restore_logs_processor} when restoring * imscp logs. It must return one array * of {@link restore_log_rule} objects */ public static function define_restore_log_rules() { $rules = array(); $rules[] = new restore_log_rule('imscp', 'add', 'view.php?id={course_module}', '{imscp}'); $rules[] = new restore_log_rule('imscp', 'update', 'view.php?id={course_module}', '{imscp}'); $rules[] = new restore_log_rule('imscp', 'view', 'view.php?id={course_module}', '{imscp}'); return $rules; } /** * Define the restore log rules that will be applied * by the {@link restore_logs_processor} when restoring * course logs. It must return one array * of {@link restore_log_rule} objects * * Note this rules are applied when restoring course logs * by the restore final task, but are defined here at * activity level. All them are rules not linked to any module instance (cmid = 0) */ public static function define_restore_log_rules_for_course() { $rules = array(); $rules[] = new restore_log_rule('imscp', 'view all', 'index.php?id={course}', null); return $rules; } } backup/moodle2/backup_imscp_activity_task.class.php000064400000004733152265517310016603 0ustar00. /** * Defines backup_imscp_activity_task class * * @package mod_imscp * @category backup * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once($CFG->dirroot . '/mod/imscp/backup/moodle2/backup_imscp_stepslib.php'); /** * Provides the steps to perform one complete backup of the IMSCP instance * * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class backup_imscp_activity_task extends backup_activity_task { /** * No specific settings for this activity */ protected function define_my_settings() { } /** * Defines a backup step to store the instance data in the imscp.xml file */ protected function define_my_steps() { $this->add_step(new backup_imscp_activity_structure_step('imscp_structure', 'imscp.xml')); } /** * Encodes URLs to the index.php and view.php scripts * * @param string $content some HTML text that eventually contains URLs to the activity instance scripts * @return string the content with the URLs encoded */ public static function encode_content_links($content) { global $CFG; $base = preg_quote($CFG->wwwroot, "/"); // Link to the list of imscps. $search = "/(" . $base . "\/mod\/imscp\/index.php\?id\=)([0-9]+)/"; $content = preg_replace($search, '$@IMSCPINDEX*$2@$', $content); // Link to imscp view by moduleid. $search = "/(" . $base . "\/mod\/imscp\/view.php\?id\=)([0-9]+)/"; $content = preg_replace($search, '$@IMSCPVIEWBYID*$2@$', $content); return $content; } } backup/moodle2/restore_imscp_stepslib.php000064400000004753152265517310014666 0ustar00. /** * Define all the restore steps that will be used by the restore_imscp_activity_task * * @package mod_imscp * @subpackage backup-moodle2 * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** * Structure step to restore one imscp activity * * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class restore_imscp_activity_structure_step extends restore_activity_structure_step { protected function define_structure() { $paths = array(); $paths[] = new restore_path_element('imscp', '/activity/imscp'); // Return the paths wrapped into standard activity structure. return $this->prepare_activity_structure($paths); } protected function process_imscp($data) { global $DB; $data = (object)$data; $oldid = $data->id; $data->course = $this->get_courseid(); // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset. // See MDL-9367. // Insert the imscp record. $newitemid = $DB->insert_record('imscp', $data); // Immediately after inserting "activity" record, call this. $this->apply_activity_instance($newitemid); } protected function after_execute() { // Add imscp related files, no need to match by itemname (just internally handled context). // Eloy Lafuente: I don't like itemid used for "imaginative" things like "revisions"! $this->add_related_files('mod_imscp', 'intro', null); $this->add_related_files('mod_imscp', 'backup', null); $this->add_related_files('mod_imscp', 'content', null); } } backup/moodle2/backup_imscp_stepslib.php000064400000004662152265517310014447 0ustar00. /** * Define all the backup steps that will be used by the backup_imscp_activity_task * * @package mod_imscp * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * Define the complete imscp structure for backup, with file and id annotations * * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class backup_imscp_activity_structure_step extends backup_activity_structure_step { protected function define_structure() { // To know if we are including userinfo. $userinfo = $this->get_setting_value('userinfo'); // Define each element separated. $imscp = new backup_nested_element('imscp', array('id'), array( 'name', 'intro', 'introformat', 'revision', 'keepold', 'structure', 'timemodified')); // Build the tree. // Define sources. $imscp->set_source_table('imscp', array('id' => backup::VAR_ACTIVITYID)); // Define id annotations - (none). // Define file annotations $imscp->annotate_files('mod_imscp', 'intro', null); // This file area hasn't itemid. $imscp->annotate_files('mod_imscp', 'backup', null); // This file area hasn't itemid. // Eloy Lafuente: I don't like itemid used for "imaginative" things like "revisions"! $imscp->annotate_files('mod_imscp', 'content', null); // Horrible use of itemid here. Ignoring for backup/restore purposes. // Return the root element (imscp), wrapped into standard activity structure. return $this->prepare_activity_structure($imscp); } } backup/moodle1/lib.php000064400000012705152265517310010644 0ustar00. /** * Provides support for the conversion of moodle1 backup to the moodle2 format * * @package mod_imscp * @copyright 2011 Andrew Davis * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** * imscp conversion handler. This resource handler is called by moodle1_mod_resource_handler * * @copyright 2011 Andrew Davis * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class moodle1_mod_imscp_handler extends moodle1_resource_successor_handler { /** @var moodle1_file_manager the file manager instance */ protected $fileman = null; /** * Converts /MOODLE_BACKUP/COURSE/MODULES/MOD/RESOURCE data * Called by moodle1_mod_resource_handler::process_resource() */ public function process_legacy_resource(array $data, ?array $raw = null) { $instanceid = $data['id']; $currentcminfo = $this->get_cminfo($instanceid); $moduleid = $currentcminfo['id']; $contextid = $this->converter->get_contextid(CONTEXT_MODULE, $moduleid); // Prepare the new imscp instance record. $imscp = array(); $imscp['id'] = $data['id']; $imscp['name'] = $data['name']; $imscp['intro'] = $data['intro']; $imscp['introformat'] = $data['introformat']; $imscp['revision'] = 1; $imscp['keepold'] = 1; $imscp['structure'] = null; $imscp['timemodified'] = $data['timemodified']; // Prepare a fresh new file manager for this instance. $this->fileman = $this->converter->get_file_manager($contextid, 'mod_imscp'); // Convert course files embedded into the intro. $this->fileman->filearea = 'intro'; $this->fileman->itemid = 0; $imscp['intro'] = moodle1_converter::migrate_referenced_files($imscp['intro'], $this->fileman); // Migrate package backup file. if ($data['reference']) { $packagename = basename($data['reference']); $packagepath = $this->converter->get_tempdir_path().'/moddata/resource/'.$data['id'].'/'.$packagename; if (file_exists($packagepath)) { $this->fileman->filearea = 'backup'; $this->fileman->itemid = 1; $this->fileman->migrate_file('moddata/resource/'.$data['id'].'/'.$packagename); } else { $this->log('missing imscp package', backup::LOG_WARNING, 'moddata/resource/'.$data['id'].'/'.$packagename); } } // Migrate extracted package data. $this->fileman->filearea = 'content'; $this->fileman->itemid = 1; $this->fileman->migrate_directory('moddata/resource/'.$data['id']); // Parse manifest. $structure = $this->parse_structure($this->converter->get_tempdir_path(). '/moddata/resource/'.$data['id'].'/imsmanifest.xml', $imscp, $contextid); $imscp['structure'] = is_array($structure) ? serialize($structure) : null; // Write imscp.xml. $this->open_xml_writer("activities/imscp_{$moduleid}/imscp.xml"); $this->xmlwriter->begin_tag('activity', array('id' => $instanceid, 'moduleid' => $moduleid, 'modulename' => 'imscp', 'contextid' => $contextid)); $this->write_xml('imscp', $imscp, array('/imscp/id')); $this->xmlwriter->end_tag('activity'); $this->close_xml_writer(); // Write inforef.xml. $this->open_xml_writer("activities/imscp_{$moduleid}/inforef.xml"); $this->xmlwriter->begin_tag('inforef'); $this->xmlwriter->begin_tag('fileref'); foreach ($this->fileman->get_fileids() as $fileid) { $this->write_xml('file', array('id' => $fileid)); } $this->xmlwriter->end_tag('fileref'); $this->xmlwriter->end_tag('inforef'); $this->close_xml_writer(); } // Internal implementation details follow. /** * Parse the IMS package structure for the $imscp->structure field * * @param string $manifestfilepath the full path to the manifest file to parse */ protected function parse_structure($manifestfilepath, $imscp, $context) { global $CFG; if (!file_exists($manifestfilepath)) { $this->log('missing imscp manifest file', backup::LOG_WARNING); return null; } $manifestfilecontents = file_get_contents($manifestfilepath); if (empty($manifestfilecontents)) { $this->log('empty imscp manifest file', backup::LOG_WARNING); return null; } require_once($CFG->dirroot.'/mod/imscp/locallib.php'); return imscp_parse_manifestfile($manifestfilecontents, $imscp, $context); } } view.php000064400000005341152265517310006241 0ustar00. /** * IMS CP module main user interface * * @package mod_imscp * @copyright 2009 Petr Skoda {@link 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/lib.php'); require_once("$CFG->dirroot/mod/imscp/locallib.php"); require_once($CFG->libdir . '/completionlib.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 = context_module::instance($cm->id); require_capability('mod/imscp:view', $context); // Completion and trigger events. imscp_view($imscp, $course, $cm, $context); $PAGE->set_url('/mod/imscp/view.php', array('id' => $cm->id)); $PAGE->requires->js('/mod/imscp/dummyapi.js', true); $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: find some better way to disable blocks and minimise footer - pagetype just for this does not seem like a good solution. // $PAGE->set_pagelayout('maxcontent'); ? $PAGE->set_title($course->shortname.': '.$imscp->name); $PAGE->set_heading($course->fullname); $PAGE->set_activity_record($imscp); // Verify imsmanifest was parsed properly. if (!$imscp->structure) { redirect(course_get_url($course->id, $cm->section), get_string('deploymenterror', 'imscp')); } echo $OUTPUT->header(); imscp_print_content($imscp, $cm, $course); echo $OUTPUT->footer(); pix/monologo.svg000064400000002715152265517310007732 0ustar00 lib.php000064400000043147152265517310006043 0ustar00. /** * Mandatory public API of imscp module * * @package mod_imscp * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once(__DIR__ . '/deprecatedlib.php'); /** * 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 or string for the module purpose. */ 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_MOD_INTRO: return true; case FEATURE_COMPLETION_TRACKS_VIEWS: return true; case FEATURE_GRADE_HAS_GRADE: return false; case FEATURE_GRADE_OUTCOMES: return false; case FEATURE_BACKUP_MOODLE2: return true; case FEATURE_SHOW_DESCRIPTION: return true; case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_INTERACTIVECONTENT; default: return null; } } /** * This function is used by the reset_course_userdata function in moodlelib. * * @param stdClass $data the data submitted from the reset course. * @return array status array */ function imscp_reset_userdata($data) { // Any changes to the list of dates that needs to be rolled should be same during course restore and course reset. // See MDL-9367. return array(); } /** * List the actions that correspond to a view of this module. * This is used by the participation report. * * Note: This is not used by new logging system. Event with * crud = 'r' and edulevel = LEVEL_PARTICIPATING will * be considered as view action. * * @return array */ function imscp_get_view_actions() { return array('view', 'view all'); } /** * List the actions that correspond to a post of this module. * This is used by the participation report. * * Note: This is not used by new logging system. Event with * crud = ('c' || 'u' || 'd') and edulevel = LEVEL_PARTICIPATING * will be considered as post action. * * @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 = context_module::instance($cmid); $imscp = $DB->get_record('imscp', array('id' => $data->id), '*', MUST_EXIST); if (!empty($data->package)) { // Save uploaded files to 'backup' filearea. $fs = get_file_storage(); $fs->delete_area_files($context->id, 'mod_imscp', 'backup', 1); file_save_draft_area_files($data->package, $context->id, 'mod_imscp', 'backup', 1, array('subdirs' => 0, 'maxfiles' => 1)); // Get filename of zip that was uploaded. $files = $fs->get_area_files($context->id, 'mod_imscp', 'backup', 1, '', false); if ($files) { // Extract package content to 'content' filearea. $package = reset($files); $packer = get_file_packer('application/zip'); $package->extract_to_storage($packer, $context->id, 'mod_imscp', 'content', 1, '/'); $structure = imscp_parse_structure($imscp, $context); $imscp->structure = is_array($structure) ? serialize($structure) : null; $DB->update_record('imscp', $imscp); } } $completiontimeexpected = !empty($data->completionexpected) ? $data->completionexpected : null; \core_completion\api::update_completion_date_event($cmid, 'imscp', $data->id, $completiontimeexpected); 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; $data->structure = null; // Better reparse structure after each update. $DB->update_record('imscp', $data); $context = context_module::instance($cmid); $imscp = $DB->get_record('imscp', array('id' => $data->id), '*', MUST_EXIST); if (!empty($data->package) && ($draftareainfo = file_get_draft_area_info($data->package)) && $draftareainfo['filecount']) { $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, 'mod_imscp', 'backup', false, "itemid ASC", false); } else { $packages = array(); } file_save_draft_area_files($data->package, $context->id, 'mod_imscp', 'backup', $imscp->revision, array('subdirs' => 0, 'maxfiles' => 1)); $files = $fs->get_area_files($context->id, 'mod_imscp', 'backup', $imscp->revision, '', false); $package = reset($files); // Purge all extracted content. $fs->delete_area_files($context->id, 'mod_imscp', 'content'); // Extract package content. if ($package) { $packer = get_file_packer('application/zip'); $package->extract_to_storage($packer, $context->id, 'mod_imscp', 'content', $imscp->revision, '/'); } // Cleanup old package files, keep current + keep old. while ($packages and (count($packages) > $imscp->keepold)) { $package = array_shift($packages); $fs->delete_area_files($context->id, 'mod_imscp', 'backup', $package->get_itemid()); } } $structure = imscp_parse_structure($imscp, $context); $imscp->structure = is_array($structure) ? serialize($structure) : null; $DB->update_record('imscp', $imscp); $completiontimeexpected = !empty($data->completionexpected) ? $data->completionexpected : null; \core_completion\api::update_completion_date_event($cmid, 'imscp', $imscp->id, $completiontimeexpected); 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; } $cm = get_coursemodule_from_instance('imscp', $id); \core_completion\api::update_completion_date_event($cm->id, 'imscp', $id, null); // Note: all context files are deleted automatically. $DB->delete_records('imscp', array('id' => $imscp->id)); return true; } /** * Lists all browsable file areas * * @package mod_imscp * @category files * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @return array */ function imscp_get_file_areas($course, $cm, $context) { $areas = array(); $areas['content'] = get_string('areacontent', 'imscp'); $areas['backup'] = get_string('areabackup', 'imscp'); return $areas; } /** * File browsing support for imscp module ontent area. * * @package mod_imscp * @category files * @param file_browser $browser file browser * @param stdClass $areas file areas * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @param string $filearea file area * @param int $itemid item ID * @param string $filepath file path * @param string $filename file name * @return 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; // Note: imscp_intro handled in file_browser automatically. if (!has_capability('moodle/course:managefiles', $context)) { // No peeking here for students! return null; } if ($filearea !== 'content' and $filearea !== 'backup') { return null; } require_once("$CFG->dirroot/mod/imscp/locallib.php"); 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, 'mod_imscp', $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); // No writing here! } /** * Serves the imscp files. * * @package mod_imscp * @category files * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @param string $filearea file area * @param array $args extra arguments * @param bool $forcedownload whether or not force download * @param array $options additional options affecting the file serving * @return bool false if file not found, does not return if found - justsend the file */ function imscp_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) { global $CFG, $DB; if ($context->contextlevel != CONTEXT_MODULE) { return false; } require_login($course, true, $cm); if ($filearea === 'content') { if (!has_capability('mod/imscp:view', $context)) { return false; } $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/mod_imscp/$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, null, 0, $forcedownload, $options); } else if ($filearea === 'backup') { 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/mod_imscp/$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, null, 0, $forcedownload, $options); } else { return false; } } /** * Return a list of page types * @param string $pagetype current page type * @param stdClass $parentcontext Block's parent context * @param stdClass $currentcontext Current context of block * @return array $modulepagetype list */ function imscp_page_type_list($pagetype, $parentcontext, $currentcontext) { $modulepagetype = array('mod-imscp-*' => get_string('page-mod-imscp-x', 'imscp')); return $modulepagetype; } /** * Export imscp resource contents * * @param stdClass $cm Course module object * @param string $baseurl Base URL for file downloads * @return array of file content */ function imscp_export_contents($cm, $baseurl) { global $DB; $contents = array(); $context = context_module::instance($cm->id); $imscp = $DB->get_record('imscp', array('id' => $cm->instance), '*', MUST_EXIST); // We export the IMSCP structure as json encoded string. $structure = array(); $structure['type'] = 'content'; $structure['filename'] = 'structure'; $structure['filepath'] = '/'; $structure['filesize'] = 0; $structure['fileurl'] = null; $structure['timecreated'] = $imscp->timemodified; $structure['timemodified'] = $imscp->timemodified; $structure['content'] = json_encode(unserialize_array($imscp->structure)); $structure['sortorder'] = 0; $structure['userid'] = null; $structure['author'] = null; $structure['license'] = null; $contents[] = $structure; // Area files. $fs = get_file_storage(); $files = $fs->get_area_files($context->id, 'mod_imscp', 'content', $imscp->revision, 'id ASC', false); foreach ($files as $fileinfo) { $file = array(); $file['type'] = 'file'; $file['filename'] = $fileinfo->get_filename(); $file['filepath'] = $fileinfo->get_filepath(); $file['filesize'] = $fileinfo->get_filesize(); $file['fileurl'] = moodle_url::make_webservice_pluginfile_url( $context->id, 'mod_imscp', 'content', $imscp->revision, $fileinfo->get_filepath(), $fileinfo->get_filename())->out(false); $file['timecreated'] = $fileinfo->get_timecreated(); $file['timemodified'] = $fileinfo->get_timemodified(); $file['sortorder'] = $fileinfo->get_sortorder(); $file['userid'] = $fileinfo->get_userid(); $file['author'] = $fileinfo->get_author(); $file['license'] = $fileinfo->get_license(); $file['mimetype'] = $fileinfo->get_mimetype(); $file['isexternalfile'] = $fileinfo->is_external_file(); if ($file['isexternalfile']) { $file['repositorytype'] = $fileinfo->get_repository_type(); } $contents[] = $file; } return $contents; } /** * Mark the activity completed (if required) and trigger the course_module_viewed event. * * @param stdClass $imscp imscp object * @param stdClass $course course object * @param stdClass $cm course module object * @param stdClass $context context object * @since Moodle 3.0 */ function imscp_view($imscp, $course, $cm, $context) { // Trigger course_module_viewed event. $params = array( 'context' => $context, 'objectid' => $imscp->id ); $event = \mod_imscp\event\course_module_viewed::create($params); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('imscp', $imscp); $event->trigger(); // Completion. $completion = new completion_info($course); $completion->set_module_viewed($cm); } /** * Check if the module has any update that affects the current user since a given time. * * @param cm_info $cm course module data * @param int $from the time to check updates from * @param array $filter if we need to check only specific updates * @return stdClass an object with the different type of areas indicating if they were updated or not * @since Moodle 3.2 */ function imscp_check_updates_since(cm_info $cm, $from, $filter = array()) { $updates = course_check_module_updates_since($cm, $from, array('content'), $filter); return $updates; } /** * This function receives a calendar event and returns the action associated with it, or null if there is none. * * This is used by block_myoverview in order to display the event appropriately. If null is returned then the event * is not displayed on the block. * * @param calendar_event $event * @param \core_calendar\action_factory $factory * @param int $userid User id to use for all capability checks, etc. Set to 0 for current user (default). * @return \core_calendar\local\event\entities\action_interface|null */ function mod_imscp_core_calendar_provide_event_action(calendar_event $event, \core_calendar\action_factory $factory, int $userid = 0) { $cm = get_fast_modinfo($event->courseid, $userid)->instances['imscp'][$event->instance]; if (!$cm->uservisible) { // The module is not visible to the user for any reason. return null; } $completion = new \completion_info($cm->get_course()); $completiondata = $completion->get_data($cm, false, $userid); if ($completiondata->completionstate != COMPLETION_INCOMPLETE) { return null; } return $factory->create_instance( get_string('view'), new \moodle_url('/mod/imscp/view.php', ['id' => $cm->id]), 1, true ); } version.php000064400000002245152265517310006754 0ustar00. /** * IMS CP module version information * * @package mod_imscp * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2025041400; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2025040800; // Requires this Moodle version. $plugin->component = 'mod_imscp'; // Full name of the plugin (used for diagnostics). $plugin->cron = 0; dummyapi.js000064400000002751152265517310006743 0ustar00// 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 . /** * IMS Content Package module including dummy SCORM API. * * @package mod * @subpackage imscp * @copyright 2009 Petr Skoda {@link 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";}; };classes/external.php000064400000016342152265517310010551 0ustar00. /** * IMSCP external API * * @package mod_imscp * @category external * @copyright 2015 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ use core_course\external\helper_for_get_mods_by_courses; use core_external\external_api; use core_external\external_function_parameters; use core_external\external_multiple_structure; use core_external\external_single_structure; use core_external\external_value; use core_external\external_warnings; use core_external\util; /** * IMSCP external functions * * @package mod_imscp * @category external * @copyright 2015 Juan Leyva * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @since Moodle 3.0 */ class mod_imscp_external extends external_api { /** * Returns description of method parameters * * @return external_function_parameters * @since Moodle 3.0 */ public static function view_imscp_parameters() { return new external_function_parameters( array( 'imscpid' => new external_value(PARAM_INT, 'imscp instance id') ) ); } /** * Simulate the imscp/view.php web interface page: trigger events, completion, etc... * * @param int $imscpid the imscp instance id * @return array of warnings and status result * @since Moodle 3.0 * @throws moodle_exception */ public static function view_imscp($imscpid) { global $DB, $CFG; require_once($CFG->dirroot . "/mod/imscp/lib.php"); $params = self::validate_parameters(self::view_imscp_parameters(), array( 'imscpid' => $imscpid )); $warnings = array(); // Request and permission validation. $imscp = $DB->get_record('imscp', array('id' => $params['imscpid']), '*', MUST_EXIST); list($course, $cm) = get_course_and_cm_from_instance($imscp, 'imscp'); $context = context_module::instance($cm->id); self::validate_context($context); require_capability('mod/imscp:view', $context); // Call the imscp/lib API. imscp_view($imscp, $course, $cm, $context); $result = array(); $result['status'] = true; $result['warnings'] = $warnings; return $result; } /** * Returns description of method result value * * @return \core_external\external_description * @since Moodle 3.0 */ public static function view_imscp_returns() { return new external_single_structure( array( 'status' => new external_value(PARAM_BOOL, 'status: true if success'), 'warnings' => new external_warnings() ) ); } /** * Describes the parameters for get_imscps_by_courses. * * @return external_function_parameters * @since Moodle 3.0 */ public static function get_imscps_by_courses_parameters() { return new external_function_parameters ( array( 'courseids' => new external_multiple_structure( new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array() ), ) ); } /** * Returns a list of IMSCP packages in a provided list of courses, * if no list is provided all IMSCP packages that the user can view will be returned. * * @param array $courseids the course ids * @return array of IMSCP packages details and possible warnings * @since Moodle 3.0 */ public static function get_imscps_by_courses($courseids = array()) { global $CFG; $returnedimscps = array(); $warnings = array(); $params = self::validate_parameters(self::get_imscps_by_courses_parameters(), array('courseids' => $courseids)); $courses = array(); if (empty($params['courseids'])) { $courses = enrol_get_my_courses(); $params['courseids'] = array_keys($courses); } // Ensure there are courseids to loop through. if (!empty($params['courseids'])) { list($courses, $warnings) = util::validate_courses($params['courseids'], $courses); // Get the imscps in this course, this function checks users visibility permissions. // We can avoid then additional validate_context calls. $imscps = get_all_instances_in_courses("imscp", $courses); foreach ($imscps as $imscp) { $imscpdetails = helper_for_get_mods_by_courses::standard_coursemodule_element_values( $imscp, 'mod_imscp', 'moodle/course:manageactivities', 'mod/imscp:view'); if (has_capability('moodle/course:manageactivities', context_module::instance($imscp->coursemodule))) { $imscpdetails['revision'] = $imscp->revision; $imscpdetails['keepold'] = $imscp->keepold; $imscpdetails['structure'] = $imscp->structure; $imscpdetails['timemodified'] = $imscp->timemodified; } $returnedimscps[] = $imscpdetails; } } $result = array(); $result['imscps'] = $returnedimscps; $result['warnings'] = $warnings; return $result; } /** * Describes the get_imscps_by_courses return value. * * @return external_single_structure * @since Moodle 3.0 */ public static function get_imscps_by_courses_returns() { return new external_single_structure( array( 'imscps' => new external_multiple_structure( new external_single_structure(array_merge( helper_for_get_mods_by_courses::standard_coursemodule_elements_returns(true), [ 'revision' => new external_value(PARAM_INT, 'Revision', VALUE_OPTIONAL), 'keepold' => new external_value(PARAM_INT, 'Number of old IMSCP to keep', VALUE_OPTIONAL), 'structure' => new external_value(PARAM_RAW, 'IMSCP structure', VALUE_OPTIONAL), 'timemodified' => new external_value(PARAM_RAW, 'Time of last modification', VALUE_OPTIONAL), ] ), 'IMS content packages') ), 'warnings' => new external_warnings(), ) ); } } classes/privacy/provider.php000064400000002736152265517310012240 0ustar00. /** * Privacy Subsystem implementation for mod_imscp. * * @package mod_imscp * @copyright 2018 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_imscp\privacy; defined('MOODLE_INTERNAL') || die(); /** * Privacy Subsystem for mod_imscp implementing null_provider. * * @copyright 2018 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason(): string { return 'privacy:metadata'; } } classes/search/activity.php000064400000002611152265517310012022 0ustar00. /** * Search area for mod_imscp activities. * * @package mod_imscp * @copyright 2015 David Monllao {@link http://www.davidmonllao.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_imscp\search; defined('MOODLE_INTERNAL') || die(); /** * Search area for mod_imscp activities. * * @package mod_imscp * @copyright 2015 David Monllao {@link http://www.davidmonllao.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class activity extends \core_search\base_activity { /** * Returns true if this area uses file indexing. * * @return bool */ public function uses_file_indexing() { return true; } } classes/event/course_module_viewed.php000064400000003140152265517310014250 0ustar00. /** * The mod_imscp course module viewed event. * * @package mod_imscp * @since Moodle 2.7 * @copyright 2014 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_imscp\event; defined('MOODLE_INTERNAL') || die(); /** * The mod_imscp course module viewed event class. * * @package mod_imscp * @since Moodle 2.7 * @copyright 2014 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class course_module_viewed extends \core\event\course_module_viewed { /** * Init method. */ protected function init() { $this->data['objecttable'] = 'imscp'; $this->data['crud'] = 'r'; $this->data['edulevel'] = self::LEVEL_PARTICIPATING; } public static function get_objectid_mapping() { return array('db' => 'imscp', 'restore' => 'imscp'); } } classes/event/course_module_instance_list_viewed.php000064400000002522152265517310017172 0ustar00. /** * The mod_imscp instance list viewed event. * * @package mod_imscp * @copyright 2014 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_imscp\event; defined('MOODLE_INTERNAL') || die(); /** * The mod_imscp instance list viewed event class. * * @package mod_imscp * @since Moodle 2.7 * @copyright 2014 Mark Nelson * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class course_module_instance_list_viewed extends \core\event\course_module_instance_list_viewed { // No code required here as the parent class handles it all. } classes/analytics/indicator/cognitive_depth.php000064400000003317152265517310016043 0ustar00. /** * Cognitive depth indicator - imscp. * * @package mod_imscp * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_imscp\analytics\indicator; defined('MOODLE_INTERNAL') || die(); /** * Cognitive depth indicator - imscp. * * @package mod_imscp * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class cognitive_depth extends activity_base { /** * Returns the name. * * If there is a corresponding '_help' string this will be shown as well. * * @return \lang_string */ public static function get_name(): \lang_string { return new \lang_string('indicator:cognitivedepth', 'mod_imscp'); } public function get_indicator_type() { return self::INDICATOR_COGNITIVE; } public function get_cognitive_depth_level(\cm_info $cm) { return self::COGNITIVE_LEVEL_1; } } classes/analytics/indicator/activity_base.php000064400000002706152265517310015517 0ustar00. /** * Activity base class. * * @package mod_imscp * @copyright 2017 onwards Ankit Agarwal * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_imscp\analytics\indicator; defined('MOODLE_INTERNAL') || die(); /** * Activity base class. * * @package mod_imscp * @copyright 2017 onwards Ankit Agarwal * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity { /** * No need to fetch grades for resources. * * @param \core_analytics\course $course * @return void */ public function fetch_student_grades(\core_analytics\course $course) { } } classes/analytics/indicator/social_breadth.php000064400000003303152265517310015626 0ustar00. /** * Social breadth indicator - imscp. * * @package mod_imscp * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace mod_imscp\analytics\indicator; defined('MOODLE_INTERNAL') || die(); /** * Social breadth indicator - imscp. * * @package mod_imscp * @copyright 2017 David Monllao {@link http://www.davidmonllao.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class social_breadth extends activity_base { /** * Returns the name. * * If there is a corresponding '_help' string this will be shown as well. * * @return \lang_string */ public static function get_name(): \lang_string { return new \lang_string('indicator:socialbreadth', 'mod_imscp'); } public function get_indicator_type() { return self::INDICATOR_SOCIAL; } public function get_social_breadth_level(\cm_info $cm) { return self::SOCIAL_LEVEL_1; } } upgrade.txt000064400000001041152265517310006737 0ustar00=== 4.5 Onwards === This file has been replaced by UPGRADING.md. See MDL-81125 for further information. === This files describes API changes in the imscp code. === 4.3 === * The `imscp_libxml_disable_entity_loader` method is deprecated, as it is no longer required from PHP 8.0 === 3.0 === * External function mod_imscp_external::get_imscps_by_courses returned parameter "name" has been changed to PARAM_RAW, this is because the new external_format_string function may return raw data if the global moodlewssettingraw parameter is used. readme.txt000064400000002003152265517310006544 0ustar00This file is part of Moodle - http://moodle.org/ Moodle is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Moodle is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Moodle. If not, see . copyright 2009 Petr Skoda (http://skodak.org) license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later IMS CP module ============= IMS CP module is a successor to the original 'ims' type plugin of Resource module. TODO: * implement a portfolio support (MDL-20074) * new backup/restore and old restore migration (MDL-20075) * move module CSS into themes (MDL-20067) locallib.php000064400000032607152265517310007055 0ustar00. /** * Private imscp module utility functions * * @package mod_imscp * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); require_once("$CFG->dirroot/mod/imscp/lib.php"); require_once("$CFG->libdir/filelib.php"); require_once("$CFG->libdir/resourcelib.php"); /** * Print IMSCP content to page. * * @param stdClass $imscp module instance. * @param stdClass $cm course module. * @param stdClass $course record. */ function imscp_print_content($imscp, $cm, $course) { global $PAGE, $CFG; $items = array_filter((array) unserialize_array($imscp->structure)); echo '
'; echo '
'; echo '
    '; foreach ($items as $item) { echo imscp_htmllize_item($item, $imscp, $cm); } echo '
'; echo ''; echo '
'; echo '
'; $PAGE->requires->js_init_call('M.mod_imscp.init'); } /** * Internal function - creates htmls structure suitable for YUI tree. */ function imscp_htmllize_item($item, $imscp, $cm) { global $CFG; if ($item['href']) { if (preg_match('|^https?://|', $item['href'])) { $url = $item['href']; } else { $context = context_module::instance($cm->id); $urlbase = "$CFG->wwwroot/pluginfile.php"; $path = '/'.$context->id.'/mod_imscp/content/'.$imscp->revision.'/'.$item['href']; $url = file_encode_url($urlbase, $path, false); } $result = "
  • ".$item['title'].''; } else { $result = '
  • '.$item['title']; } if ($item['subitems']) { $result .= '
      '; foreach ($item['subitems'] as $subitem) { $result .= imscp_htmllize_item($subitem, $imscp, $cm); } $result .= '
    '; } $result .= '
  • '; return $result; } /** * Parse an IMS content package's manifest file to determine its structure * @param object $imscp * @param object $context * @return array */ function imscp_parse_structure($imscp, $context) { $fs = get_file_storage(); if (!$manifestfile = $fs->get_file($context->id, 'mod_imscp', 'content', $imscp->revision, '/', 'imsmanifest.xml')) { return null; } return imscp_parse_manifestfile($manifestfile->get_content(), $imscp, $context); } /** * Parse the contents of a IMS package's manifest file. * @param string $manifestfilecontents the contents of the manifest file * @return array */ function imscp_parse_manifestfile($manifestfilecontents, $imscp, $context) { $doc = new DOMDocument(); if (!$doc->loadXML($manifestfilecontents, 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')) { // If href not found look for . $fileresources = $res->getElementsByTagName('file'); foreach ($fileresources as $file) { $href = $file->getAttribute('href'); } if (pathinfo($href, PATHINFO_EXTENSION) == 'xml') { $href = imscp_recursive_href($href, $imscp, $context); } if (empty($href)) { continue; } } else { $href = $href->nodeValue; } if (strpos($href, 'http://') !== 0) { $href = $xmlbase.$href; } // Item 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_href($manifestfilename, $imscp, $context) { $fs = get_file_storage(); $dirname = dirname($manifestfilename); $filename = basename($manifestfilename); if ($dirname !== '/') { $dirname = "/$dirname/"; } if (!$manifestfile = $fs->get_file($context->id, 'mod_imscp', 'content', $imscp->revision, $dirname, $filename)) { return null; } $doc = new DOMDocument(); if (!$doc->loadXML($manifestfile->get_content(), LIBXML_NONET)) { return null; } $xmlresources = $doc->getElementsByTagName('resource'); foreach ($xmlresources as $res) { if (!$href = $res->attributes->getNamedItem('href')) { $fileresources = $res->getElementsByTagName('file'); foreach ($fileresources as $file) { $href = $file->getAttribute('href'); if (pathinfo($href, PATHINFO_EXTENSION) == 'xml') { $href = imscp_recursive_href($href, $imscp, $context); } if (pathinfo($href, PATHINFO_EXTENSION) == 'htm' || pathinfo($href, PATHINFO_EXTENSION) == 'html') { return $href; } } } } return $manifestfilename; } 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 * * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ 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, 'component' => 'mod_imscp', '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() { return $this->get_filtered_children('*', false, true); } /** * Help function to return files matching extensions or their count * * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg') * @param bool|int $countonly if false returns the children, if an int returns just the * count of children but stops counting when $countonly number of children is reached * @param bool $returnemptyfolders if true returns items that don't have matching files inside * @return array|int array of file_info instances or the count */ private function get_filtered_children($extensions = '*', $countonly = false, $returnemptyfolders = false) { global $DB; $params = array('contextid' => $this->context->id, 'component' => 'mod_imscp', 'filearea' => $this->filearea); $sql = 'SELECT DISTINCT itemid FROM {files} WHERE contextid = :contextid AND component = :component AND filearea = :filearea'; if (!$returnemptyfolders) { $sql .= ' AND filename <> :emptyfilename'; $params['emptyfilename'] = '.'; } list($sql2, $params2) = $this->build_search_files_sql($extensions); $sql .= ' '.$sql2; $params = array_merge($params, $params2); if ($countonly !== false) { $sql .= ' ORDER BY itemid'; } $rs = $DB->get_recordset_sql($sql, $params); $children = array(); foreach ($rs as $record) { if ($child = $this->browser->get_file_info($this->context, 'mod_imscp', $this->filearea, $record->itemid)) { $children[] = $child; if ($countonly !== false && count($children) >= $countonly) { break; } } } $rs->close(); if ($countonly !== false) { return count($children); } return $children; } /** * Returns list of children which are either files matching the specified extensions * or folders that contain at least one such file. * * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg') * @return array of file_info instances */ public function get_non_empty_children($extensions = '*') { return $this->get_filtered_children($extensions, false); } /** * Returns the number of children which are either files matching the specified extensions * or folders containing at least one such file. * * @param string|array $extensions, for example '*' or array('.gif','.jpg') * @param int $limit stop counting after at least $limit non-empty children are found * @return int */ public function count_non_empty_children($extensions = '*', $limit = 1) { return $this->get_filtered_children($extensions, $limit); } /** * Returns parent file_info instance * @return file_info or null for root */ public function get_parent() { return $this->browser->get_file_info($this->context); } } module.js000064400000031044152265517310006400 0ustar00// This file is part of Moodle - http://moodle.org/ // // Moodle is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Moodle is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . /** * Javascript helper function for IMS Content Package module. * * @package mod * @subpackage imscp * @copyright 2009 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ M.mod_imscp = {}; M.mod_imscp.init = function(Y) { var imscp_layout_widget; var imscp_current_node; var imscp_buttons = []; var imscp_bloody_labelclick = false; Y.use('yui2-resize', 'yui2-dragdrop', 'yui2-container', 'yui2-button', 'yui2-layout', 'yui2-treeview', 'yui2-json', 'yui2-event', function(Y) { var imscp_activate_item_by_index = function(index) { imscp_activate_item(Y.YUI2.widget.TreeView.getNode('imscp_tree', index)); }; var imscp_activate_item = function(node) { if (!node) { return; } imscp_current_node = node; imscp_current_node.highlight(); var content = new Y.YUI2.util.Element('imscp_content'); var obj; if (node.href) { try { // First try IE way - it can not set name attribute later // and also it has some restrictions on DOM access from object tag. obj = document.createElement('