2009-11-01 15:24:58 +00:00
< ? php
2006-08-10 11:32:48 +00:00
2008-09-09 08:30:00 +00:00
require_once ( " $CFG->dirroot /mod/scorm/lib.php " );
2006-09-26 07:56:07 +00:00
/// Constants and settings for module scorm
2007-01-24 10:39:24 +00:00
define ( 'UPDATE_NEVER' , '0' );
define ( 'UPDATE_ONCHANGE' , '1' );
define ( 'UPDATE_EVERYDAY' , '2' );
define ( 'UPDATE_EVERYTIME' , '3' );
2006-11-21 16:12:19 +00:00
define ( 'SCO_ALL' , 0 );
define ( 'SCO_DATA' , 1 );
define ( 'SCO_ONLY' , 2 );
2006-09-26 07:56:07 +00:00
define ( 'GRADESCOES' , '0' );
define ( 'GRADEHIGHEST' , '1' );
define ( 'GRADEAVERAGE' , '2' );
define ( 'GRADESUM' , '3' );
define ( 'HIGHESTATTEMPT' , '0' );
define ( 'AVERAGEATTEMPT' , '1' );
define ( 'FIRSTATTEMPT' , '2' );
define ( 'LASTATTEMPT' , '3' );
2008-09-09 08:30:00 +00:00
/// Local Library of functions for module scorm
2006-09-26 07:56:07 +00:00
2008-11-11 02:46:20 +00:00
/**
* Returns an array of the popup options for SCORM and each options default value
2008-11-29 17:51:47 +00:00
*
2008-11-11 02:46:20 +00:00
* @ return array an array of popup options as the key and their defaults as the value
*/
function scorm_get_popup_options_array (){
global $CFG ;
$cfg_scorm = get_config ( 'scorm' );
2008-11-29 17:51:47 +00:00
return array ( 'resizable' => isset ( $cfg_scorm -> resizable ) ? $cfg_scorm -> resizable : 0 ,
'scrollbars' => isset ( $cfg_scorm -> scrollbars ) ? $cfg_scorm -> scrollbars : 0 ,
'directories' => isset ( $cfg_scorm -> directories ) ? $cfg_scorm -> directories : 0 ,
2008-11-11 04:45:39 +00:00
'location' => isset ( $cfg_scorm -> location ) ? $cfg_scorm -> location : 0 ,
2008-11-29 17:51:47 +00:00
'menubar' => isset ( $cfg_scorm -> menubar ) ? $cfg_scorm -> menubar : 0 ,
'toolbar' => isset ( $cfg_scorm -> toolbar ) ? $cfg_scorm -> toolbar : 0 ,
'status' => isset ( $cfg_scorm -> status ) ? $cfg_scorm -> status : 0 );
2008-11-11 02:46:20 +00:00
}
/**
* Returns an array of the array of what grade options
2008-11-29 17:51:47 +00:00
*
2008-11-11 02:46:20 +00:00
* @ return array an array of what grade options
*/
function scorm_get_grade_method_array (){
return array ( GRADESCOES => get_string ( 'gradescoes' , 'scorm' ),
GRADEHIGHEST => get_string ( 'gradehighest' , 'scorm' ),
GRADEAVERAGE => get_string ( 'gradeaverage' , 'scorm' ),
2008-11-29 17:51:47 +00:00
GRADESUM => get_string ( 'gradesum' , 'scorm' ));
2008-11-11 02:46:20 +00:00
}
/**
* Returns an array of the array of what grade options
2008-11-29 17:51:47 +00:00
*
2008-11-11 02:46:20 +00:00
* @ return array an array of what grade options
*/
function scorm_get_what_grade_array (){
return array ( HIGHESTATTEMPT => get_string ( 'highestattempt' , 'scorm' ),
AVERAGEATTEMPT => get_string ( 'averageattempt' , 'scorm' ),
FIRSTATTEMPT => get_string ( 'firstattempt' , 'scorm' ),
LASTATTEMPT => get_string ( 'lastattempt' , 'scorm' ));
}
/**
* Returns an array of the array of skip view options
2008-11-29 17:51:47 +00:00
*
2008-11-11 02:46:20 +00:00
* @ return array an array of skip view options
*/
function scorm_get_skip_view_array (){
return array ( 0 => get_string ( 'never' ),
1 => get_string ( 'firstaccess' , 'scorm' ),
2 => get_string ( 'always' ));
}
/**
* Returns an array of the array of hide table of contents options
2008-11-29 17:51:47 +00:00
*
2008-11-11 02:46:20 +00:00
* @ return array an array of hide table of contents options
*/
function scorm_get_hidetoc_array (){
return array ( 0 => get_string ( 'sided' , 'scorm' ),
1 => get_string ( 'hidden' , 'scorm' ),
2 => get_string ( 'popupmenu' , 'scorm' ));
}
/**
* Returns an array of the array of update frequency options
2008-11-29 17:51:47 +00:00
*
2008-11-11 02:46:20 +00:00
* @ return array an array of update frequency options
*/
function scorm_get_updatefreq_array (){
return array ( 0 => get_string ( 'never' ),
1 => get_string ( 'onchanges' , 'scorm' ),
2 => get_string ( 'everyday' , 'scorm' ),
3 => get_string ( 'everytime' , 'scorm' ));
}
/**
* Returns an array of the array of popup display options
2008-11-29 17:51:47 +00:00
*
2008-11-11 02:46:20 +00:00
* @ return array an array of popup display options
*/
function scorm_get_popup_display_array (){
return array ( 0 => get_string ( 'iframe' , 'scorm' ),
1 => get_string ( 'popup' , 'scorm' ));
}
/**
* Returns an array of the array of attempt options
2008-11-29 17:51:47 +00:00
*
2008-11-11 02:46:20 +00:00
* @ return array an array of attempt options
*/
function scorm_get_attempts_array (){
$attempts = array ( 0 => get_string ( 'nolimit' , 'scorm' ),
1 => get_string ( 'attempt1' , 'scorm' ));
2008-11-29 17:51:47 +00:00
2008-11-11 02:46:20 +00:00
for ( $i = 2 ; $i <= 6 ; $i ++ ) {
$attempts [ $i ] = get_string ( 'attemptsx' , 'scorm' , $i );
}
2008-11-29 17:51:47 +00:00
2008-11-11 02:46:20 +00:00
return $attempts ;
}
2008-09-09 08:30:00 +00:00
/**
* Extracts scrom package , sets up all variables .
* Called whenever scorm changes
* @ param object $scorm instance - fields are updated and changes saved into database
* @ param bool $full force full update if true
* @ return void
*/
function scorm_parse ( $scorm , $full ) {
global $CFG , $DB ;
2008-11-11 02:46:20 +00:00
$cfg_scorm = get_config ( 'scorm' );
2007-01-18 15:54:56 +00:00
2008-09-09 08:30:00 +00:00
if ( ! isset ( $scorm -> cmid )) {
$cm = get_coursemodule_from_instance ( 'scorm' , $scorm -> id );
$scorm -> cmid = $cm -> id ;
}
$context = get_context_instance ( CONTEXT_MODULE , $scorm -> cmid );
$newhash = $scorm -> sha1hash ;
2006-09-26 07:56:07 +00:00
2008-09-09 08:30:00 +00:00
if ( $scorm -> scormtype === SCORM_TYPE_LOCAL or $scorm -> scormtype === SCORM_TYPE_LOCALSYNC ) {
2006-09-26 07:56:07 +00:00
2008-09-09 08:30:00 +00:00
$fs = get_file_storage ();
$packagefile = false ;
2006-08-10 11:32:48 +00:00
2008-09-09 08:30:00 +00:00
if ( $scorm -> scormtype === SCORM_TYPE_LOCAL ) {
if ( $packagefile = $fs -> get_file ( $context -> id , 'scorm_package' , 0 , '/' , $scorm -> reference )) {
$newhash = $packagefile -> get_contenthash ();
} else {
$newhash = null ;
}
} else {
2008-11-11 02:46:20 +00:00
if ( ! $cfg_scorm -> allowtypelocalsync ) {
2008-09-09 08:30:00 +00:00
// sorry - localsync disabled
return ;
}
if ( $scorm -> reference !== '' and ( ! $full or $scorm -> sha1hash !== sha1 ( $scorm -> reference ))) {
$fs -> delete_area_files ( $context -> id , 'scorm_package' );
$file_record = array ( 'contextid' => $context -> id , 'filearea' => 'scorm_package' , 'itemid' => 0 , 'filepath' => '/' );
if ( $packagefile = $fs -> create_file_from_url ( $file_record , $scorm -> reference )) {
$newhash = sha1 ( $scorm -> reference );
2006-08-11 12:26:06 +00:00
} else {
2008-09-09 08:30:00 +00:00
$newhash = null ;
2006-08-11 12:26:06 +00:00
}
2006-08-10 11:32:48 +00:00
}
}
2008-09-09 08:30:00 +00:00
if ( $packagefile ) {
if ( ! $full and $packagefile and $scorm -> sha1hash === $newhash ) {
if ( strpos ( $scorm -> version , 'SCORM' ) !== false ) {
if ( $fs -> get_file ( $context -> id , 'scorm_content' , 0 , '/' , 'imsmanifest.xml' )) {
// no need to update
return ;
2006-07-23 23:48:09 +00:00
}
2008-09-09 08:30:00 +00:00
} else if ( strpos ( $scorm -> version , 'AICC' ) !== false ) {
// TODO: add more sanity checks - something really exists in scorm_content area
return ;
}
}
// now extract files
$fs -> delete_area_files ( $context -> id , 'scorm_content' );
$packer = get_file_packer ( 'application/zip' );
$packagefile -> extract_to_storage ( $packer , $context -> id , 'scorm_content' , 0 , '/' );
} else if ( ! $full ) {
return ;
}
if ( $manifest = $fs -> get_file ( $context -> id , 'scorm_content' , 0 , '/' , 'imsmanifest.xml' )) {
require_once ( " $CFG->dirroot /mod/scorm/datamodels/scormlib.php " );
// SCORM
if ( ! scorm_parse_scorm ( $scorm , $manifest )) {
$scorm -> version = 'ERROR' ;
}
} else {
require_once ( " $CFG->dirroot /mod/scorm/datamodels/aicclib.php " );
// AICC
if ( ! scorm_parse_aicc ( $scorm )) {
$scorm -> version = 'ERROR' ;
}
}
2008-11-11 02:46:20 +00:00
} else if ( $scorm -> scormtype === SCORM_TYPE_EXTERNAL and $cfg_scorm -> allowtypeexternal ) {
2008-09-09 08:30:00 +00:00
if ( ! $full and $scorm -> sha1hash === sha1 ( $scorm -> reference )) {
return ;
}
require_once ( " $CFG->dirroot /mod/scorm/datamodels/scormlib.php " );
// SCORM only, AICC can not be external
if ( ! scorm_parse_scorm ( $scorm , $scorm -> reference )) {
$scorm -> version = 'ERROR' ;
}
$newhash = sha1 ( $scorm -> reference );
2008-11-11 02:46:20 +00:00
} else if ( $scorm -> scormtype === SCORM_TYPE_IMSREPOSITORY and ! empty ( $CFG -> repositoryactivate ) and $cfg_scorm -> allowtypeimsrepository ) {
2008-09-09 08:30:00 +00:00
if ( ! $full and $scorm -> sha1hash === sha1 ( $scorm -> reference )) {
return ;
}
require_once ( " $CFG->dirroot /mod/scorm/datamodels/scormlib.php " );
if ( ! scorm_parse_scorm ( $scorm , $CFG -> repository . substr ( $scorm -> reference , 1 ) . '/imsmanifest.xml' )) {
$scorm -> version = 'ERROR' ;
}
$newhash = sha1 ( $scorm -> reference );
2006-07-23 23:48:09 +00:00
} else {
2008-09-09 08:30:00 +00:00
// sorry, disabled type
return ;
2006-07-23 23:48:09 +00:00
}
2008-09-09 08:30:00 +00:00
$scorm -> revision ++ ;
$scorm -> sha1hash = $newhash ;
$DB -> update_record ( 'scorm' , $scorm );
2006-07-23 23:48:09 +00:00
}
2008-09-09 08:30:00 +00:00
2006-08-31 08:34:13 +00:00
function scorm_array_search ( $item , $needle , $haystacks , $strict = false ) {
if ( ! empty ( $haystacks )) {
foreach ( $haystacks as $key => $element ) {
if ( $strict ) {
if ( $element -> { $item } === $needle ) {
return $key ;
}
} else {
if ( $element -> { $item } == $needle ) {
return $key ;
2006-07-23 23:48:09 +00:00
}
}
}
}
2006-08-31 08:34:13 +00:00
return false ;
2006-07-23 23:48:09 +00:00
}
2006-08-31 08:34:13 +00:00
function scorm_repeater ( $what , $times ) {
if ( $times <= 0 ) {
return null ;
}
$return = '' ;
for ( $i = 0 ; $i < $times ; $i ++ ) {
$return .= $what ;
}
return $return ;
}
2006-07-23 23:48:09 +00:00
2006-08-31 08:34:13 +00:00
function scorm_external_link ( $link ) {
// check if a link is external
$result = false ;
$link = strtolower ( $link );
if ( substr ( $link , 0 , 7 ) == 'http://' ) {
$result = true ;
} else if ( substr ( $link , 0 , 8 ) == 'https://' ) {
$result = true ;
} else if ( substr ( $link , 0 , 4 ) == 'www.' ) {
$result = true ;
}
return $result ;
2006-07-23 23:48:09 +00:00
}
2006-11-21 16:12:19 +00:00
/**
* Returns an object containing all datas relative to the given sco ID
*
* @ param integer $id The sco ID
* @ return mixed ( false if sco id does not exists )
*/
2007-06-06 09:19:18 +00:00
2006-11-21 16:12:19 +00:00
function scorm_get_sco ( $id , $what = SCO_ALL ) {
2008-06-05 10:02:26 +00:00
global $DB ;
if ( $sco = $DB -> get_record ( 'scorm_scoes' , array ( 'id' => $id ))) {
2006-11-21 16:12:19 +00:00
$sco = ( $what == SCO_DATA ) ? new stdClass () : $sco ;
2008-06-05 10:02:26 +00:00
if (( $what != SCO_ONLY ) && ( $scodatas = $DB -> get_records ( 'scorm_scoes_data' , array ( 'scoid' => $id )))) {
2006-11-21 16:12:19 +00:00
foreach ( $scodatas as $scodata ) {
2007-07-23 15:38:31 +00:00
$sco -> { $scodata -> name } = $scodata -> value ;
2006-11-21 16:12:19 +00:00
}
2008-06-05 10:02:26 +00:00
} else if (( $what != SCO_ONLY ) && ( ! ( $scodatas = $DB -> get_records ( 'scorm_scoes_data' , array ( 'scoid' => $id ))))) {
2008-09-09 08:30:00 +00:00
$sco -> parameters = '' ;
2006-11-21 16:12:19 +00:00
}
return $sco ;
} else {
return false ;
}
}
2008-08-07 21:44:42 +00:00
/**
* Returns an object ( array ) containing all the scoes data related to the given sco ID
*
* @ param integer $id The sco ID
* @ param integer $organisation an organisation ID - defaults to false if not required
* @ return mixed ( false if there are no scoes or an array )
*/
function scorm_get_scoes ( $id , $organisation = false ) {
2008-08-21 07:32:19 +00:00
global $DB ;
2008-08-07 21:44:42 +00:00
$organizationsql = '' ;
2008-08-21 07:32:19 +00:00
$queryarray = array ( 'scorm' => $id );
2008-08-07 21:44:42 +00:00
if ( ! empty ( $organisation )) {
2008-08-21 07:32:19 +00:00
$queryarray [ 'organization' ] = $organisation ;
2008-08-07 21:44:42 +00:00
}
2008-08-21 07:32:19 +00:00
if ( $scoes = $DB -> get_records ( 'scorm_scoes' , $queryarray , 'id ASC' )) {
2008-08-07 21:44:42 +00:00
// drop keys so that it is a simple array as expected
$scoes = array_values ( $scoes );
foreach ( $scoes as $sco ) {
2008-08-21 07:32:19 +00:00
if ( $scodatas = $DB -> get_records ( 'scorm_scoes_data' , array ( 'scoid' => $sco -> id ))) {
2008-08-07 21:44:42 +00:00
foreach ( $scodatas as $scodata ) {
2008-09-23 21:09:46 +00:00
$sco -> { $scodata -> name } = $scodata -> value ;
2008-08-07 21:44:42 +00:00
}
}
}
return $scoes ;
} else {
return false ;
}
}
2008-09-16 20:32:50 +00:00
function scorm_insert_track ( $userid , $scormid , $scoid , $attempt , $element , $value , $forcecompleted = false ) {
2008-06-05 10:02:26 +00:00
global $DB ;
2006-07-23 23:48:09 +00:00
$id = null ;
2008-09-16 20:32:50 +00:00
if ( $forcecompleted ) {
//TODO - this could be broadened to encompass SCORM 2004 in future
if (( $element == 'cmi.core.lesson_status' ) && ( $value == 'incomplete' )) {
if ( $track = $DB -> get_record_select ( 'scorm_scoes_track' , 'userid=? AND scormid=? AND scoid=? AND attempt=? AND element=\'cmi.core.score.raw\'' , array ( $userid , $scormid , $scoid , $attempt ))) {
$value = 'completed' ;
}
}
if ( $element == 'cmi.core.score.raw' ) {
if ( $tracktest = $DB -> get_record_select ( 'scorm_scoes_track' , 'userid=? AND scormid=? AND scoid=? AND attempt=? AND element=\'cmi.core.lesson_status\'' , array ( $userid , $scormid , $scoid , $attempt ))) {
if ( $tracktest -> value == " incomplete " ) {
$tracktest -> value = " completed " ;
$idtest = $DB -> update_record ( 'scorm_scoes_track' , $tracktest );
}
}
}
}
2008-06-05 10:02:26 +00:00
if ( $track = $DB -> get_record ( 'scorm_scoes_track' , array ( 'userid' => $userid , 'scormid' => $scormid , 'scoid' => $scoid , 'attempt' => $attempt , 'element' => $element ))) {
2009-02-25 22:56:59 +00:00
$track -> value = addslashes_js ( $value );
2006-07-23 23:48:09 +00:00
$track -> timemodified = time ();
2008-06-05 10:02:26 +00:00
$id = $DB -> update_record ( 'scorm_scoes_track' , $track );
2006-07-23 23:48:09 +00:00
} else {
$track -> userid = $userid ;
$track -> scormid = $scormid ;
$track -> scoid = $scoid ;
$track -> attempt = $attempt ;
$track -> element = $element ;
2009-02-25 22:56:59 +00:00
$track -> value = addslashes_js ( $value );
2006-07-23 23:48:09 +00:00
$track -> timemodified = time ();
2008-06-05 10:02:26 +00:00
$id = $DB -> insert_record ( 'scorm_scoes_track' , $track );
2006-07-23 23:48:09 +00:00
}
2008-09-09 08:30:00 +00:00
if ( strstr ( $element , '.score.raw' ) ||
2008-08-24 21:10:09 +00:00
(( $element == 'cmi.core.lesson_status' || $element == 'cmi.completion_status' ) && ( $track -> value == 'completed' || $track -> value == 'passed' ))) {
$scorm = $DB -> get_record ( 'scorm' , array ( 'id' => $scormid ));
$grademethod = $scorm -> grademethod % 10 ;
2008-11-09 22:27:18 +00:00
include_once ( 'lib.php' );
scorm_update_grades ( $scorm , $userid );
2007-11-05 07:31:35 +00:00
}
2008-09-09 08:30:00 +00:00
2006-07-23 23:48:09 +00:00
return $id ;
}
function scorm_get_tracks ( $scoid , $userid , $attempt = '' ) {
/// Gets all tracks of specified sco and user
2008-06-05 10:02:26 +00:00
global $CFG , $DB ;
2006-07-23 23:48:09 +00:00
if ( empty ( $attempt )) {
2008-06-05 10:02:26 +00:00
if ( $scormid = $DB -> get_field ( 'scorm_scoes' , 'scorm' , array ( 'id' => $scoid ))) {
2006-07-23 23:48:09 +00:00
$attempt = scorm_get_last_attempt ( $scormid , $userid );
} else {
$attempt = 1 ;
}
}
2008-06-05 10:02:26 +00:00
if ( $tracks = $DB -> get_records ( 'scorm_scoes_track' , array ( 'userid' => $userid , 'scoid' => $scoid , 'attempt' => $attempt ), 'element ASC' )) {
2006-07-23 23:48:09 +00:00
$usertrack -> userid = $userid ;
2008-09-09 08:30:00 +00:00
$usertrack -> scoid = $scoid ;
2006-09-26 07:56:07 +00:00
// Defined in order to unify scorm1.2 and scorm2004
2006-07-23 23:48:09 +00:00
$usertrack -> score_raw = '' ;
$usertrack -> status = '' ;
$usertrack -> total_time = '00:00:00' ;
$usertrack -> session_time = '00:00:00' ;
$usertrack -> timemodified = 0 ;
foreach ( $tracks as $track ) {
$element = $track -> element ;
2009-02-26 18:19:05 +00:00
$track -> value = stripslashes ( $track -> value );
2006-07-23 23:48:09 +00:00
$usertrack -> { $element } = $track -> value ;
switch ( $element ) {
2008-12-20 06:20:43 +00:00
case 'x.start.time' :
$usertrack -> x_start_time = $track -> value ;
break ;
2006-08-10 11:32:48 +00:00
case 'cmi.core.lesson_status' :
case 'cmi.completion_status' :
if ( $track -> value == 'not attempted' ) {
$track -> value = 'notattempted' ;
2008-09-09 08:30:00 +00:00
}
2006-08-10 11:32:48 +00:00
$usertrack -> status = $track -> value ;
2008-09-09 08:30:00 +00:00
break ;
2006-07-23 23:48:09 +00:00
case 'cmi.core.score.raw' :
case 'cmi.score.raw' :
2009-02-04 18:37:18 +00:00
$usertrack -> score_raw = sprintf ( '%0d' , $track -> value );
2008-09-09 08:30:00 +00:00
break ;
2006-07-23 23:48:09 +00:00
case 'cmi.core.session_time' :
case 'cmi.session_time' :
$usertrack -> session_time = $track -> value ;
2008-09-09 08:30:00 +00:00
break ;
2006-07-23 23:48:09 +00:00
case 'cmi.core.total_time' :
case 'cmi.total_time' :
$usertrack -> total_time = $track -> value ;
2008-09-09 08:30:00 +00:00
break ;
}
2006-07-23 23:48:09 +00:00
if ( isset ( $track -> timemodified ) && ( $track -> timemodified > $usertrack -> timemodified )) {
$usertrack -> timemodified = $track -> timemodified ;
2008-09-09 08:30:00 +00:00
}
2008-07-24 23:08:30 +00:00
}
2008-09-09 08:30:00 +00:00
if ( is_array ( $usertrack )) {
2008-07-27 21:19:01 +00:00
ksort ( $usertrack );
}
2006-07-23 23:48:09 +00:00
return $usertrack ;
} else {
return false ;
}
}
2008-12-20 06:20:43 +00:00
/* Find the start and finsh time for a a given SCO attempt
*
* @ param int $scormid SCORM Id
* @ param int $scoid SCO Id
* @ param int $userid User Id
* @ param int $attemt Attempt Id
*
* @ return object start and finsh time EPOC secods
*
*/
function scorm_get_sco_runtime ( $scormid , $scoid , $userid , $attempt = 1 ) {
2009-12-16 22:14:17 +00:00
global $DB ;
2008-12-20 06:20:43 +00:00
$timedata = new object ();
$sql = ! empty ( $scoid ) ? " userid= $userid AND scormid= $scormid AND scoid= $scoid AND attempt= $attempt " : " userid= $userid AND scormid= $scormid AND attempt= $attempt " ;
$tracks = $DB -> get_records_select ( 'scorm_scoes_track' , " $sql ORDER BY timemodified ASC " );
if ( $tracks ) {
$tracks = array_values ( $tracks );
}
if ( $start_track = $DB -> get_records_select ( 'scorm_scoes_track' , " $sql AND element='x.start.time' ORDER BY scoid ASC " )) {
$start_track = array_values ( $start_track );
$timedata -> start = $start_track [ 0 ] -> value ;
}
else if ( $tracks ) {
$timedata -> start = $tracks [ 0 ] -> timemodified ;
}
else {
$timedata -> start = false ;
}
if ( $tracks && $track = array_pop ( $tracks )) {
$timedata -> finish = $track -> timemodified ;
}
else {
$timedata -> finish = $timedata -> start ;
}
return $timedata ;
}
2006-08-31 08:34:13 +00:00
function scorm_get_user_data ( $userid ) {
2008-06-05 10:02:26 +00:00
global $DB ;
2006-08-31 08:34:13 +00:00
/// Gets user info required to display the table of scorm results
/// for report.php
2006-07-23 23:48:09 +00:00
2008-06-05 10:02:26 +00:00
return $DB -> get_record ( 'user' , array ( 'id' => $userid ), 'firstname, lastname, picture' );
2006-08-31 08:34:13 +00:00
}
2006-07-23 23:48:09 +00:00
2006-09-26 07:56:07 +00:00
function scorm_grade_user_attempt ( $scorm , $userid , $attempt = 1 , $time = false ) {
2008-06-05 10:02:26 +00:00
global $DB ;
2008-09-09 08:30:00 +00:00
$attemptscore = NULL ;
2006-09-26 07:56:07 +00:00
$attemptscore -> scoes = 0 ;
$attemptscore -> values = 0 ;
$attemptscore -> max = 0 ;
$attemptscore -> sum = 0 ;
$attemptscore -> lastmodify = 0 ;
2008-09-09 08:30:00 +00:00
2008-06-05 10:02:26 +00:00
if ( ! $scoes = $DB -> get_records ( 'scorm_scoes' , array ( 'scorm' => $scorm -> id ))) {
2006-09-26 07:56:07 +00:00
return NULL ;
2006-07-23 23:48:09 +00:00
}
2008-08-22 01:30:28 +00:00
// this treatment is necessary as the whatgrade field was not in the DB
// and so whatgrade and grademethod are combined in grademethod 10s are whatgrade
// and 1s are grademethod
2006-09-26 07:56:07 +00:00
$grademethod = $scorm -> grademethod % 10 ;
2008-09-09 08:30:00 +00:00
foreach ( $scoes as $sco ) {
2006-08-31 08:34:13 +00:00
if ( $userdata = scorm_get_tracks ( $sco -> id , $userid , $attempt )) {
if (( $userdata -> status == 'completed' ) || ( $userdata -> status == 'passed' )) {
2006-09-26 07:56:07 +00:00
$attemptscore -> scoes ++ ;
2008-09-09 08:30:00 +00:00
}
2009-12-18 07:22:50 +00:00
if ( isset ( $userdata -> score_raw )) {
2006-09-26 07:56:07 +00:00
$attemptscore -> values ++ ;
$attemptscore -> sum += $userdata -> score_raw ;
$attemptscore -> max = ( $userdata -> score_raw > $attemptscore -> max ) ? $userdata -> score_raw : $attemptscore -> max ;
if ( isset ( $userdata -> timemodified ) && ( $userdata -> timemodified > $attemptscore -> lastmodify )) {
$attemptscore -> lastmodify = $userdata -> timemodified ;
} else {
$attemptscore -> lastmodify = 0 ;
}
2008-09-09 08:30:00 +00:00
}
}
2006-07-23 23:48:09 +00:00
}
2006-08-31 08:34:13 +00:00
switch ( $grademethod ) {
2006-09-26 07:56:07 +00:00
case GRADEHIGHEST :
$score = $attemptscore -> max ;
2008-09-09 08:30:00 +00:00
break ;
2006-09-26 07:56:07 +00:00
case GRADEAVERAGE :
if ( $attemptscore -> values > 0 ) {
$score = $attemptscore -> sum / $attemptscore -> values ;
2006-08-11 12:26:06 +00:00
} else {
2006-09-26 07:56:07 +00:00
$score = 0 ;
2008-09-09 08:30:00 +00:00
}
break ;
2006-09-26 07:56:07 +00:00
case GRADESUM :
$score = $attemptscore -> sum ;
2008-09-09 08:30:00 +00:00
break ;
2006-09-26 07:56:07 +00:00
case GRADESCOES :
$score = $attemptscore -> scoes ;
2008-08-21 03:12:08 +00:00
break ;
default :
$score = $attemptscore -> max ; // Remote Learner GRADEHIGHEST is default
2006-08-11 12:26:06 +00:00
}
2006-09-26 07:56:07 +00:00
if ( $time ) {
$result = new stdClass ();
$result -> score = $score ;
$result -> time = $attemptscore -> lastmodify ;
} else {
$result = $score ;
}
return $result ;
}
function scorm_grade_user ( $scorm , $userid , $time = false ) {
2008-08-22 01:30:28 +00:00
// this treatment is necessary as the whatgrade field was not in the DB
// and so whatgrade and grademethod are combined in grademethod 10s are whatgrade
// and 1s are grademethod
2006-09-26 07:56:07 +00:00
$whatgrade = intval ( $scorm -> grademethod / 10 );
2008-08-22 01:30:28 +00:00
// insure we dont grade user beyond $scorm->maxattempt settings
$lastattempt = scorm_get_last_attempt ( $scorm -> id , $userid );
if ( $scorm -> maxattempt != 0 && $lastattempt >= $scorm -> maxattempt ){
$lastattempt = $scorm -> maxattempt ;
}
2006-09-26 07:56:07 +00:00
switch ( $whatgrade ) {
case FIRSTATTEMPT :
return scorm_grade_user_attempt ( $scorm , $userid , 1 , $time );
2008-09-09 08:30:00 +00:00
break ;
2006-09-26 07:56:07 +00:00
case LASTATTEMPT :
return scorm_grade_user_attempt ( $scorm , $userid , scorm_get_last_attempt ( $scorm -> id , $userid ), $time );
break ;
case HIGHESTATTEMPT :
$maxscore = 0 ;
$attempttime = 0 ;
for ( $attempt = 1 ; $attempt <= $lastattempt ; $attempt ++ ) {
$attemptscore = scorm_grade_user_attempt ( $scorm , $userid , $attempt , $time );
if ( $time ) {
if ( $attemptscore -> score > $maxscore ) {
$maxscore = $attemptscore -> score ;
$attempttime = $attemptscore -> time ;
}
} else {
$maxscore = $attemptscore > $maxscore ? $attemptscore : $maxscore ;
}
}
if ( $time ) {
$result = new stdClass ();
$result -> score = $maxscore ;
$result -> time = $attempttime ;
return $result ;
} else {
return $maxscore ;
}
break ;
case AVERAGEATTEMPT :
$lastattempt = scorm_get_last_attempt ( $scorm -> id , $userid );
$sumscore = 0 ;
for ( $attempt = 1 ; $attempt <= $lastattempt ; $attempt ++ ) {
$attemptscore = scorm_grade_user_attempt ( $scorm , $userid , $attempt , $time );
if ( $time ) {
$sumscore += $attemptscore -> score ;
} else {
$sumscore += $attemptscore ;
}
}
if ( $lastattempt > 0 ) {
$score = $sumscore / $lastattempt ;
} else {
$score = 0 ;
}
if ( $time ) {
$result = new stdClass ();
$result -> score = $score ;
$result -> time = $attemptscore -> time ;
return $result ;
} else {
return $score ;
}
break ;
}
2006-07-23 23:48:09 +00:00
}
2006-09-26 14:40:00 +00:00
function scorm_count_launchable ( $scormid , $organization = '' ) {
2008-06-05 10:02:26 +00:00
global $DB ;
$sqlorganization = '' ;
$params = array ( $scormid );
2006-09-26 14:40:00 +00:00
if ( ! empty ( $organization )) {
2008-06-05 10:02:26 +00:00
$sqlorganization = " AND organization=? " ;
$params [] = $organization ;
2006-09-26 14:40:00 +00:00
}
2008-08-15 03:30:05 +00:00
$params [] = '' ; // empty launch
return $DB -> count_records_select ( 'scorm_scoes' , " scorm = ? $sqlorganization AND launch <> ? " , $params );
2006-07-23 23:48:09 +00:00
}
2006-08-31 08:34:13 +00:00
function scorm_get_last_attempt ( $scormid , $userid ) {
2008-06-05 10:02:26 +00:00
global $DB ;
2006-08-31 08:34:13 +00:00
/// Find the last attempt number for the given user id and scorm id
2008-06-05 10:02:26 +00:00
if ( $lastattempt = $DB -> get_record ( 'scorm_scoes_track' , array ( 'userid' => $userid , 'scormid' => $scormid ), 'max(attempt) as a' )) {
2006-08-31 08:34:13 +00:00
if ( empty ( $lastattempt -> a )) {
return '1' ;
} else {
return $lastattempt -> a ;
2006-07-23 23:48:09 +00:00
}
2008-09-16 20:32:50 +00:00
} else {
return false ;
2006-07-23 23:48:09 +00:00
}
}
function scorm_course_format_display ( $user , $course ) {
2009-07-02 11:09:15 +00:00
global $CFG , $DB , $PAGE , $OUTPUT ;
2006-07-23 23:48:09 +00:00
$strupdate = get_string ( 'update' );
$strmodule = get_string ( 'modulename' , 'scorm' );
2006-08-31 10:37:33 +00:00
$context = get_context_instance ( CONTEXT_COURSE , $course -> id );
2006-07-23 23:48:09 +00:00
echo '<div class="mod-scorm">' ;
if ( $scorms = get_all_instances_in_course ( 'scorm' , $course )) {
2008-09-09 08:30:00 +00:00
// The module SCORM activity with the least id is the course
2006-07-23 23:48:09 +00:00
$scorm = current ( $scorms );
if ( ! $cm = get_coursemodule_from_instance ( 'scorm' , $scorm -> id , $course -> id )) {
2008-06-15 11:00:30 +00:00
print_error ( 'invalidcoursemodule' );
2006-07-23 23:48:09 +00:00
}
$colspan = '' ;
$headertext = '<table width="100%"><tr><td class="title">' . get_string ( 'name' ) . ': <b>' . format_string ( $scorm -> name ) . '</b>' ;
2006-08-31 08:34:13 +00:00
if ( has_capability ( 'moodle/course:manageactivities' , $context )) {
2009-05-06 08:59:29 +00:00
if ( $PAGE -> user_is_editing ()) {
2006-07-23 23:48:09 +00:00
// Display update icon
$path = $CFG -> wwwroot . '/course' ;
$headertext .= '<span class="commands">' .
'<a title="' . $strupdate . '" href="' . $path . '/mod.php?update=' . $cm -> id . '&sesskey=' . sesskey () . '">' .
2009-12-16 21:50:45 +00:00
'<img src="' . $OUTPUT -> pix_url ( 't/edit' ) . '" class="iconsmall" alt="' . $strupdate . '" /></a></span>' ;
2006-07-23 23:48:09 +00:00
}
$headertext .= '</td>' ;
// Display report link
2008-06-05 10:02:26 +00:00
$trackedusers = $DB -> get_record ( 'scorm_scoes_track' , array ( 'scormid' => $scorm -> id ), 'count(distinct(userid)) as c' );
2006-07-23 23:48:09 +00:00
if ( $trackedusers -> c > 0 ) {
$headertext .= '<td class="reportlink">' .
2007-01-04 18:23:55 +00:00
'<a ' . $CFG -> frametarget . '" href="' . $CFG -> wwwroot . '/mod/scorm/report.php?id=' . $cm -> id . '">' .
2006-07-23 23:48:09 +00:00
get_string ( 'viewallreports' , 'scorm' , $trackedusers -> c ) . '</a>' ;
} else {
$headertext .= '<td class="reportlink">' . get_string ( 'noreports' , 'scorm' );
}
$colspan = ' colspan="2"' ;
2008-09-09 08:30:00 +00:00
}
2009-04-20 19:57:04 +00:00
$options = ( object ) array ( 'noclean' => true );
2009-04-22 05:10:08 +00:00
$headertext .= '</td></tr><tr><td' . $colspan . '>' . get_string ( 'summary' ) . ':<br />' . format_module_intro ( 'scorm' , $scorm , $scorm -> coursemodule ) . '</td></tr></table>' ;
2009-08-18 05:16:50 +00:00
echo $OUTPUT -> box ( $headertext , 'generalbox boxwidthwide' );
2006-07-23 23:48:09 +00:00
scorm_view_display ( $user , $scorm , 'view.php?id=' . $course -> id , $cm , '100%' );
} else {
2006-08-31 10:29:16 +00:00
if ( has_capability ( 'moodle/course:update' , $context )) {
2006-07-23 23:48:09 +00:00
// Create a new activity
2006-08-31 08:34:13 +00:00
redirect ( $CFG -> wwwroot . '/course/mod.php?id=' . $course -> id . '&section=0&sesskey=' . sesskey () . '&add=scorm' );
2006-07-23 23:48:09 +00:00
} else {
2009-08-18 05:16:50 +00:00
echo $OUTPUT -> notification ( 'Could not find a scorm course here' );
2006-07-23 23:48:09 +00:00
}
}
echo '</div>' ;
}
2006-08-31 08:34:13 +00:00
function scorm_view_display ( $user , $scorm , $action , $cm , $boxwidth = '' ) {
2009-07-28 09:32:23 +00:00
global $CFG , $DB , $PAGE , $OUTPUT ;
2007-01-25 07:20:38 +00:00
2008-09-09 08:30:00 +00:00
if ( $scorm -> updatefreq == UPDATE_EVERYTIME ) {
scorm_parse ( $scorm , false );
2007-01-25 07:20:38 +00:00
}
2006-07-23 23:48:09 +00:00
$organization = optional_param ( 'organization' , '' , PARAM_INT );
2008-09-16 20:32:50 +00:00
if ( $scorm -> displaycoursestructure == 1 ) {
2009-08-18 05:16:50 +00:00
echo $OUTPUT -> box_start ( 'generalbox boxaligncenter' );
2006-07-23 23:48:09 +00:00
?>
2007-03-14 00:16:22 +00:00
< div class = " structurehead " >< ? php print_string ( 'contents' , 'scorm' ) ?> </div>
2006-07-23 23:48:09 +00:00
< ? php
2008-09-16 20:32:50 +00:00
}
2006-07-23 23:48:09 +00:00
if ( empty ( $organization )) {
$organization = $scorm -> launch ;
}
2008-07-27 21:19:01 +00:00
if ( $orgs = $DB -> get_records_menu ( 'scorm_scoes' , array ( 'scorm' => $scorm -> id , 'organization' => '' , 'launch' => '' ), 'id' , 'id,title' )) {
2006-07-23 23:48:09 +00:00
if ( count ( $orgs ) > 1 ) {
?>
2008-07-29 00:42:28 +00:00
< div class = 'scorm-center' >
2006-07-23 23:48:09 +00:00
< ? php print_string ( 'organizations' , 'scorm' ) ?>
2007-01-04 21:32:36 +00:00
< form id = 'changeorg' method = 'post' action = '<?php echo $action ?>' >
2009-11-01 15:24:58 +00:00
< ? php
2009-08-10 08:38:45 +00:00
$select = new html_select ();
2009-08-04 02:05:32 +00:00
$select -> options = $orgs ;
$select -> name = 'organization' ;
$select -> selectedvalue = $organization ;
$select -> add_action ( 'change' , 'submit_form_by_id' , array ( 'id' => 'changeorg' ));
2009-11-01 15:24:58 +00:00
echo $OUTPUT -> select ( $select );
2009-07-28 09:32:23 +00:00
?>
2006-07-23 23:48:09 +00:00
</ form >
</ div >
< ? php
}
}
$orgidentifier = '' ;
2006-11-21 16:12:19 +00:00
if ( $sco = scorm_get_sco ( $organization , SCO_ONLY )) {
if (( $sco -> organization == '' ) && ( $sco -> launch == '' )) {
$orgidentifier = $sco -> identifier ;
2006-07-23 23:48:09 +00:00
} else {
2006-11-21 16:12:19 +00:00
$orgidentifier = $sco -> organization ;
2006-07-23 23:48:09 +00:00
}
}
2007-03-08 12:06:26 +00:00
/*
$orgidentifier = '' ;
2008-06-05 10:02:26 +00:00
if ( $org = $DB -> get_record ( 'scorm_scoes' , array ( 'id' => $organization ))) {
2007-03-08 12:06:26 +00:00
if (( $org -> organization == '' ) && ( $org -> launch == '' )) {
$orgidentifier = $org -> identifier ;
} else {
$orgidentifier = $org -> organization ;
}
} */
2006-08-31 08:34:13 +00:00
$scorm -> version = strtolower ( clean_param ( $scorm -> version , PARAM_SAFEDIR )); // Just to be safe
2006-11-28 03:04:50 +00:00
if ( ! file_exists ( $CFG -> dirroot . '/mod/scorm/datamodels/' . $scorm -> version . 'lib.php' )) {
$scorm -> version = 'scorm_12' ;
}
2006-08-31 08:34:13 +00:00
require_once ( $CFG -> dirroot . '/mod/scorm/datamodels/' . $scorm -> version . 'lib.php' );
2006-07-23 23:48:09 +00:00
$result = scorm_get_toc ( $user , $scorm , 'structlist' , $orgidentifier );
$incomplete = $result -> incomplete ;
2007-03-08 12:06:26 +00:00
2008-09-16 20:32:50 +00:00
// do we want the TOC to be displayed?
if ( $scorm -> displaycoursestructure == 1 ) {
echo $result -> toc ;
2009-08-18 05:16:50 +00:00
echo $OUTPUT -> box_end ();
2008-09-16 20:32:50 +00:00
}
2008-11-29 17:51:47 +00:00
2008-09-16 20:32:50 +00:00
// is this the first attempt ?
$attemptcount = scorm_get_attempt_count ( $user , $scorm );
2008-11-29 17:51:47 +00:00
2008-09-16 20:32:50 +00:00
// do not give the player launch FORM if the SCORM object is locked after the final attempt
if ( $scorm -> lastattemptlock == 0 || $result -> attemptleft > 0 ) {
2006-07-23 23:48:09 +00:00
?>
2008-07-29 00:42:28 +00:00
< div class = " scorm-center " >
2008-09-08 00:31:15 +00:00
< form id = " theform " method = " post " action = " <?php echo $CFG->wwwroot ?>/mod/scorm/player.php " >
2006-07-23 23:48:09 +00:00
< ? php
if ( $scorm -> hidebrowse == 0 ) {
2007-01-25 13:49:50 +00:00
print_string ( 'mode' , 'scorm' );
2006-07-23 23:48:09 +00:00
echo ': <input type="radio" id="b" name="mode" value="browse" /><label for="b">' . get_string ( 'browse' , 'scorm' ) . '</label>' . " \n " ;
2007-01-16 13:21:19 +00:00
echo '<input type="radio" id="n" name="mode" value="normal" checked="checked" /><label for="n">' . get_string ( 'normal' , 'scorm' ) . " </label> \n " ;
2006-07-23 23:48:09 +00:00
} else {
2007-01-16 13:21:19 +00:00
echo '<input type="hidden" name="mode" value="normal" />' . " \n " ;
2006-07-23 23:48:09 +00:00
}
2008-09-16 20:32:50 +00:00
if ( $scorm -> forcenewattempt == 1 ) {
if ( $incomplete === false ) {
echo '<input type="hidden" name="newattempt" value="on" />' . " \n " ;
}
} elseif ( $attemptcount != 0 && ( $incomplete === false ) && (( $result -> attemptleft > 0 ) || ( $scorm -> maxattempt == 0 ))) {
2006-07-23 23:48:09 +00:00
?>
2008-09-16 20:32:50 +00:00
< br />
< input type = " checkbox " id = " a " name = " newattempt " />
< label for = " a " >< ? php print_string ( 'newattempt' , 'scorm' ) ?> </label>
2006-07-23 23:48:09 +00:00
< ? php
}
?>
< br />
2008-09-08 00:31:15 +00:00
< input type = " hidden " name = " scoid " />
2008-09-01 23:04:59 +00:00
< input type = " hidden " name = " id " value = " <?php echo $cm->id ?> " />
2006-07-23 23:48:09 +00:00
< input type = " hidden " name = " currentorg " value = " <?php echo $orgidentifier ?> " />
2007-03-15 20:50:12 +00:00
< input type = " submit " value = " <?php print_string('enter','scorm') ?> " />
2006-07-23 23:48:09 +00:00
</ form >
</ div >
< ? php
2008-09-16 20:32:50 +00:00
}
2006-07-23 23:48:09 +00:00
}
2008-08-15 03:30:05 +00:00
2007-03-08 12:06:26 +00:00
function scorm_simple_play ( $scorm , $user ) {
2008-06-05 10:02:26 +00:00
global $DB ;
2008-12-01 03:32:39 +00:00
$result = false ;
if ( $scorm -> updatefreq == UPDATE_EVERYTIME ) {
scorm_parse ( $scorm , false );
}
$scoes = $DB -> get_records_select ( 'scorm_scoes' , 'scorm = ? AND launch <> ?' , array ( $scorm -> id , $DB -> sql_empty ()));
2008-12-07 21:54:49 +00:00
if ( $scoes ) {
2008-12-01 03:32:39 +00:00
if ( $scorm -> skipview >= 1 ) {
$sco = current ( $scoes );
if ( scorm_get_tracks ( $sco -> id , $user -> id ) === false ) {
header ( 'Location: player.php?a=' . $scorm -> id . '&scoid=' . $sco -> id );
$result = true ;
} else if ( $scorm -> skipview == 2 ) {
header ( 'Location: player.php?a=' . $scorm -> id . '&scoid=' . $sco -> id );
$result = true ;
}
}
}
return $result ;
2007-03-08 12:06:26 +00:00
}
/*
2006-09-26 14:40:00 +00:00
function scorm_simple_play ( $scorm , $user ) {
2008-06-05 10:02:26 +00:00
global $DB ;
2006-09-26 14:40:00 +00:00
$result = false ;
2008-06-05 10:02:26 +00:00
if ( $scoes = $DB -> get_records_select ( 'scorm_scoes' , 'scorm=? AND launch<>""' , array ( $scorm -> id ))) {
2007-01-16 13:21:19 +00:00
if ( count ( $scoes ) == 1 ) {
if ( $scorm -> skipview >= 1 ) {
$sco = current ( $scoes );
if ( scorm_get_tracks ( $sco -> id , $user -> id ) === false ) {
header ( 'Location: player.php?a=' . $scorm -> id . '&scoid=' . $sco -> id );
$result = true ;
} else if ( $scorm -> skipview == 2 ) {
header ( 'Location: player.php?a=' . $scorm -> id . '&scoid=' . $sco -> id );
$result = true ;
}
2006-09-26 14:40:00 +00:00
}
}
}
return $result ;
}
2007-03-08 12:06:26 +00:00
*/
2007-08-28 02:54:37 +00:00
function scorm_get_count_users ( $scormid , $groupingid = null ) {
2008-06-05 10:02:26 +00:00
global $CFG , $DB ;
2008-09-09 08:30:00 +00:00
2007-08-28 02:54:37 +00:00
if ( ! empty ( $CFG -> enablegroupings ) && ! empty ( $groupingid )) {
$sql = " SELECT COUNT(DISTINCT st.userid)
2008-06-05 10:02:26 +00:00
FROM { scorm_scoes_track } st
INNER JOIN { groups_members } gm ON st . userid = gm . userid
2008-09-09 08:30:00 +00:00
INNER JOIN { groupings_groups } gg ON gm . groupid = gg . groupid
2008-06-05 10:02:26 +00:00
WHERE st . scormid = ? AND gg . groupingid = ?
2007-08-28 02:54:37 +00:00
" ;
2008-06-05 10:02:26 +00:00
$params = array ( $scormid , $groupingid );
2007-08-28 02:54:37 +00:00
} else {
$sql = " SELECT COUNT(DISTINCT st.userid)
2008-09-09 08:30:00 +00:00
FROM { scorm_scoes_track } st
2008-06-05 10:02:26 +00:00
WHERE st . scormid = ?
2007-08-28 02:54:37 +00:00
" ;
2008-06-05 10:02:26 +00:00
$params = array ( $scormid );
2007-08-28 02:54:37 +00:00
}
2008-09-09 08:30:00 +00:00
2008-06-05 10:02:26 +00:00
return ( $DB -> count_records_sql ( $sql , $params ));
2007-08-28 02:54:37 +00:00
}
2008-09-08 19:45:50 +00:00
/**
* Build up the JavaScript representation of an array element
*
* @ param string $sversion SCORM API version
* @ param array $userdata User track data
* @ param string $element_name Name of array element to get values for
* @ param array $children list of sub elements of this array element that also need instantiating
* @ return None
2008-11-29 17:51:47 +00:00
*/
2008-09-08 19:45:50 +00:00
function scorm_reconstitute_array_element ( $sversion , $userdata , $element_name , $children ) {
// reconstitute comments_from_learner and comments_from_lms
$current = '' ;
2008-09-24 23:12:09 +00:00
$current_subelement = '' ;
$current_sub = '' ;
2008-09-08 19:45:50 +00:00
$count = 0 ;
2008-09-24 23:12:09 +00:00
$count_sub = 0 ;
2008-11-29 17:51:47 +00:00
2008-09-08 19:45:50 +00:00
// filter out the ones we want
$element_list = array ();
foreach ( $userdata as $element => $value ){
if ( substr ( $element , 0 , strlen ( $element_name )) == $element_name ) {
$element_list [ $element ] = $value ;
}
}
2008-11-29 17:51:47 +00:00
2008-09-08 19:45:50 +00:00
// sort elements in .n array order
uksort ( $element_list , " scorm_element_cmp " );
2008-11-29 17:51:47 +00:00
2008-09-08 19:45:50 +00:00
// generate JavaScript
foreach ( $element_list as $element => $value ){
if ( $sversion == 'scorm_13' ) {
2008-09-25 23:59:32 +00:00
$element = preg_replace ( '/\.(\d+)\./' , " .N \$ 1. " , $element );
2008-09-08 19:45:50 +00:00
preg_match ( '/\.(N\d+)\./' , $element , $matches );
} else {
2008-09-25 23:59:32 +00:00
$element = preg_replace ( '/\.(\d+)\./' , " _ \$ 1. " , $element );
2008-09-08 19:45:50 +00:00
preg_match ( '/\_(\d+)\./' , $element , $matches );
}
if ( count ( $matches ) > 0 && $current != $matches [ 1 ]) {
2008-09-24 23:12:09 +00:00
if ( $count_sub > 0 ) {
echo ' ' . $element_name . '_' . $current . '.' . $current_subelement . '._count = ' . $count_sub . " ; \n " ;
}
2008-11-29 17:51:47 +00:00
$current = $matches [ 1 ];
2008-09-08 19:45:50 +00:00
$count ++ ;
2008-09-24 23:12:09 +00:00
$current_subelement = '' ;
$current_sub = '' ;
$count_sub = 0 ;
2008-09-08 19:45:50 +00:00
$end = strpos ( $element , $matches [ 1 ]) + strlen ( $matches [ 1 ]);
$subelement = substr ( $element , 0 , $end );
echo ' ' . $subelement . " = new Object(); \n " ;
// now add the children
foreach ( $children as $child ) {
echo ' ' . $subelement . " . " . $child . " = new Object(); \n " ;
echo ' ' . $subelement . " . " . $child . " ._children = " . $child . " _children; \n " ;
}
}
2008-11-29 17:51:47 +00:00
2008-09-24 23:12:09 +00:00
// now - flesh out the second level elements if there are any
if ( $sversion == 'scorm_13' ) {
2008-09-25 23:59:32 +00:00
$element = preg_replace ( '/(.*?\.N\d+\..*?)\.(\d+)\./' , " \$ 1.N \$ 2. " , $element );
2008-09-24 23:12:09 +00:00
preg_match ( '/.*?\.N\d+\.(.*?)\.(N\d+)\./' , $element , $matches );
} else {
2008-09-25 23:59:32 +00:00
$element = preg_replace ( '/(.*?\_\d+\..*?)\.(\d+)\./' , " \$ 1_ \$ 2. " , $element );
2008-09-24 23:12:09 +00:00
preg_match ( '/.*?\_\d+\.(.*?)\_(\d+)\./' , $element , $matches );
}
2008-11-29 17:51:47 +00:00
2008-09-24 23:12:09 +00:00
// check the sub element type
if ( count ( $matches ) > 0 && $current_subelement != $matches [ 1 ]) {
if ( $count_sub > 0 ) {
echo ' ' . $element_name . '_' . $current . '.' . $current_subelement . '._count = ' . $count_sub . " ; \n " ;
}
$current_subelement = $matches [ 1 ];
$current_sub = '' ;
$count_sub = 0 ;
$end = strpos ( $element , $matches [ 1 ]) + strlen ( $matches [ 1 ]);
$subelement = substr ( $element , 0 , $end );
echo ' ' . $subelement . " = new Object(); \n " ;
}
2008-11-29 17:51:47 +00:00
2008-09-24 23:12:09 +00:00
// now check the subelement subscript
if ( count ( $matches ) > 0 && $current_sub != $matches [ 2 ]) {
2008-11-29 17:51:47 +00:00
$current_sub = $matches [ 2 ];
2008-09-24 23:12:09 +00:00
$count_sub ++ ;
$end = strrpos ( $element , $matches [ 2 ]) + strlen ( $matches [ 2 ]);
$subelement = substr ( $element , 0 , $end );
echo ' ' . $subelement . " = new Object(); \n " ;
}
2008-11-29 17:51:47 +00:00
2008-09-08 19:45:50 +00:00
echo ' ' . $element . ' = \'' . $value . " '; \n " ;
}
2008-09-24 23:12:09 +00:00
if ( $count_sub > 0 ) {
echo ' ' . $element_name . '_' . $current . '.' . $current_subelement . '._count = ' . $count_sub . " ; \n " ;
}
2008-09-08 19:45:50 +00:00
if ( $count > 0 ) {
echo ' ' . $element_name . '._count = ' . $count . " ; \n " ;
}
}
/**
* Build up the JavaScript representation of an array element
*
* @ param string $a left array element
* @ param string $b right array element
* @ return comparator - 0 , 1 , - 1
2008-11-29 17:51:47 +00:00
*/
2008-09-08 19:45:50 +00:00
function scorm_element_cmp ( $a , $b ) {
2008-09-24 23:12:09 +00:00
preg_match ( '/.*?(\d+)\./' , $a , $matches );
2008-09-08 19:45:50 +00:00
$left = intval ( $matches [ 1 ]);
2008-09-24 23:12:09 +00:00
preg_match ( '/.?(\d+)\./' , $b , $matches );
2008-09-08 19:45:50 +00:00
$right = intval ( $matches [ 1 ]);
if ( $left < $right ) {
return - 1 ; // smaller
} elseif ( $left > $right ) {
return 1 ; // bigger
} else {
2008-09-24 23:12:09 +00:00
// look for a second level qualifier eg cmi.interactions_0.correct_responses_0.pattern
if ( preg_match ( '/.*?(\d+)\.(.*?)\.(\d+)\./' , $a , $matches )) {
$leftterm = intval ( $matches [ 2 ]);
$left = intval ( $matches [ 3 ]);
if ( preg_match ( '/.*?(\d+)\.(.*?)\.(\d+)\./' , $b , $matches )) {
$rightterm = intval ( $matches [ 2 ]);
$right = intval ( $matches [ 3 ]);
if ( $leftterm < $rightterm ) {
return - 1 ; // smaller
} elseif ( $leftterm > $rightterm ) {
return 1 ; // bigger
} else {
if ( $left < $right ) {
return - 1 ; // smaller
} elseif ( $left > $right ) {
return 1 ; // bigger
}
}
}
}
// fall back for no second level matches or second level matches are equal
2008-09-08 19:45:50 +00:00
return 0 ; // equal to
}
}
2008-09-16 20:32:50 +00:00
/**
* Generate the user attempt status string
*
* @ param object $user Current context user
* @ param object $scorm a moodle scrom object - mdl_scorm
* @ return string - Attempt status string
2008-11-29 17:51:47 +00:00
*/
2008-09-16 20:32:50 +00:00
function scorm_get_attempt_status ( $user , $scorm ) {
global $DB ;
2008-11-29 17:51:47 +00:00
2008-09-16 20:32:50 +00:00
$attempts = $DB -> get_records_select ( 'scorm_scoes_track' , " element='cmi.core.score.raw' AND userid=? AND scormid=? " , array ( $user -> id , $scorm -> id ), 'attempt' , 'attempt AS attemptnumber, value AS grade' );
if ( empty ( $attempts )) {
$attemptcount = 0 ;
} else {
$attemptcount = count ( $attempts );
}
2008-11-29 17:51:47 +00:00
2008-09-16 20:32:50 +00:00
$result = '<p>' . get_string ( 'noattemptsallowed' , 'scorm' ) . ': ' ;
if ( $scorm -> maxattempt > 0 ) {
$result .= $scorm -> maxattempt . '<BR>' ;
} else {
$result .= get_string ( 'unlimited' ) . '<BR>' ;
}
$result .= get_string ( 'noattemptsmade' , 'scorm' ) . ': ' . $attemptcount . '<BR>' ;
$gradereported = 0 ;
$gradesum = 0 ;
switch ( $scorm -> grademethod ) {
case GRADEHIGHEST :
$grademethod = get_string ( 'gradehighest' , 'scorm' );
break ;
case GRADEAVERAGE :
$grademethod = get_string ( 'gradeaverage' , 'scorm' );
break ;
case GRADESUM :
$grademethod = get_string ( 'gradesum' , 'scorm' );
break ;
case GRADESCOES :
$grademethod = get_string ( 'gradescoes' , 'scorm' );
break ;
}
2008-11-29 17:51:47 +00:00
2008-09-16 20:32:50 +00:00
if ( ! empty ( $attempts )) {
foreach ( $attempts as $attempt ) {
$gradereported = scorm_grade_user_attempt ( $scorm , $user -> id , $attempt -> attemptnumber );
$result .= get_string ( 'gradeforattempt' , 'scorm' ) . ' ' . $attempt -> attemptnumber . ': ' . $attempt -> grade . '%<BR>' ;
}
}
$result .= get_string ( 'grademethod' , 'scorm' ) . ': ' . $grademethod ;
if ( empty ( $attempts )) {
$result .= '<BR>' . get_string ( 'gradereported' , 'scorm' ) . ': ' . get_string ( 'none' ) . '<BR>' ;
} else {
$result .= '<BR>' . get_string ( 'gradereported' , 'scorm' ) . ': ' . $gradereported . ( $scorm -> grademethod == GRADESCOES ? '' : '%' ) . '<BR>' ;
}
$result .= '</p>' ;
if ( $attemptcount >= $scorm -> maxattempt and $scorm -> maxattempt > 0 ) {
$result .= '<p><font color="#cc0000">' . get_string ( 'exceededmaxattempts' , 'scorm' ) . '</font></p>' ;
}
return $result ;
}
/**
* Get SCORM attempt count
*
* @ param object $user Current context user
* @ param object $scorm a moodle scrom object - mdl_scorm
* @ return int - no . of attempts so far
2008-11-29 17:51:47 +00:00
*/
2008-09-16 20:32:50 +00:00
function scorm_get_attempt_count ( $user , $scorm ) {
global $DB ;
$attemptcount = 0 ;
$element = 'cmi.core.score.raw' ;
if ( $scorm -> version == 'scorm1_3' ) {
$element = 'cmi.score.raw' ;
}
$attempts = $DB -> get_records_select ( 'scorm_scoes_track' , " element=? AND userid=? AND scormid=? " , array ( $element , $user -> id , $scorm -> id ), 'attempt' , 'attempt AS attemptnumber, value AS grade' );
if ( ! empty ( $attempts )) {
$attemptcount = count ( $attempts );
}
return $attemptcount ;
}
2008-09-16 22:50:16 +00:00
/**
* Figure out with this is a debug situation
*
* @ param object $scorm a moodle scrom object - mdl_scorm
* @ return boolean - debugging true / false
2008-11-29 17:51:47 +00:00
*/
2008-09-16 22:50:16 +00:00
function scorm_debugging ( $scorm ) {
global $CFG , $USER ;
2008-11-11 02:46:20 +00:00
$cfg_scorm = get_config ( 'scorm' );
2008-11-29 17:51:47 +00:00
2008-11-11 02:46:20 +00:00
if ( ! $cfg_scorm -> allowapidebug ) {
2008-09-16 22:50:16 +00:00
return false ;
}
$identifier = $USER -> username . ':' . $scorm -> name ;
2008-11-11 02:46:20 +00:00
$test = $cfg_scorm -> apidebugmask ;
2008-09-16 22:50:16 +00:00
// check the regex is only a short list of safe characters
if ( ! preg_match ( '/^[\w\s\*\.\?\+\:\_\\\]+$/' , $test )) {
return false ;
}
$res = false ;
eval ( '$res = preg_match(\'/^' . $test . '/\', $identifier) ? true : false;' );
return $res ;
}
2008-11-29 17:51:47 +00:00
/**
* Delete Scorm tracks for selected users
*
* @ param array $attemptids list of attempts that need to be deleted
* @ param int $scormid ID of Scorm
*
* return bool true deleted all responses , false failed deleting an attempt - stopped here
*/
function scorm_delete_responses ( $attemptids , $scormid ) {
if ( ! is_array ( $attemptids ) || empty ( $attemptids )) {
return false ;
}
foreach ( $attemptids as $num => $attemptid ) {
if ( empty ( $attemptid )) {
unset ( $attemptids [ $num ]);
}
}
foreach ( $attemptids as $attempt ) {
$keys = explode ( ':' , $attempt );
if ( count ( $keys ) == 2 ) {
$userid = clean_param ( $keys [ 0 ], PARAM_INT );
$attemptid = clean_param ( $keys [ 1 ], PARAM_INT );
if ( ! $userid || ! $attemptid || ! scorm_delete_attempt ( $userid , $scormid , $attemptid )) {
return false ;
}
} else {
return false ;
}
}
return true ;
}
/**
* Delete Scorm tracks for selected users
*
* @ param int $userid ID of User
* @ param int $scormid ID of Scorm
* @ param int $attemptid user attempt that need to be deleted
*
* return bool true suceeded
*/
function scorm_delete_attempt ( $userid , $scormid , $attemptid ) {
global $DB ;
$DB -> delete_records ( 'scorm_scoes_track' , array ( 'userid' => $userid , 'scormid' => $scormid , 'attempt' => $attemptid ));
return true ;
}
2009-12-18 10:10:04 +00:00
/**
* Converts SCORM date / time notation to human - readable format
* The function works with both SCORM 1.2 and SCORM 2004 time formats
* @ param $datetime string SCORM date / time
* @ return string human - readable date / time
*/
function scorm_format_date_time ( $datetime ) {
// fetch date/time strings
$stryears = get_string ( 'numyears' );
$strmonths = get_string ( 'nummonths' );
$strdays = get_string ( 'numdays' );
$strhours = get_string ( 'numhours' );
$strminutes = get_string ( 'numminutes' );
$strseconds = get_string ( 'numseconds' );
if ( $datetime [ 0 ] == 'P' ) {
// if timestamp starts with 'P' - it's a SCORM 2004 format
// this regexp discards empty sections, takes Month/Minute ambiguity into consideration,
// and outputs filled sections, discarding leading zeroes and any format literals
// also saves the only zero before seconds decimals (if there are any) and discards decimals if they are zero
$pattern = array ( '#([A-Z])0+Y#' , '#([A-Z])0+M#' , '#([A-Z])0+D#' , '#P(|\d+Y)0*(\d+)M#' , '#0*(\d+)Y#' , '#0*(\d+)D#' , '#P#' ,
'#([A-Z])0+H#' , '#([A-Z])[0.]+S#' , '#\.0+S#' , '#T(|\d+H)0*(\d+)M#' , '#0*(\d+)H#' , '#0+\.(\d+)S#' , '#0*([\d.]+)S#' , '#T#' );
$replace = array ( '$1' , '$1' , '$1' , '$1$2' . $strmonths . ' ' , '$1' . $stryears . ' ' , '$1' . $strdays . ' ' , '' ,
'$1' , '$1' , 'S' , '$1$2' . $strminutes . ' ' , '$1' . $strhours . ' ' , '0.$1' . $strseconds , '$1' . $strseconds , '' );
} else {
// else we have SCORM 1.2 format there
// first convert the timestamp to some SCORM 2004-like format for conveniency
$datetime = preg_replace ( '#^(\d+):(\d+):([\d.]+)$#' , 'T$1H$2M$3S' , $datetime );
// then convert in the same way as SCORM 2004
$pattern = array ( '#T0+H#' , '#([A-Z])0+M#' , '#([A-Z])[0.]+S#' , '#\.0+S#' , '#0*(\d+)H#' , '#0*(\d+)M#' , '#0+\.(\d+)S#' , '#0*([\d.]+)S#' , '#T#' );
$replace = array ( 'T' , '$1' , '$1' , 'S' , '$1' . $strhours . ' ' , '$1' . $strminutes . ' ' , '0.$1' . $strseconds , '$1' . $strseconds , '' );
//$pattern = '##';
//$replace = '';
}
$result = preg_replace ( $pattern , $replace , $datetime );
return $result ;
}