Step 49 – SCO Initialization

I’ve addressed handling of the LMSSetValue() and LMSGetValue(), LMSCommit(), and LMSFinish() calls. The remaining piece of the puzzle is to look at how the RTE is initialized.

In Rev 1 of the code, the course/SCO call to LMSInitialize() caused an AJAX request to be sent to the server where a script called initialize.php was executed. The one thing that this doesn’t do is to transfer all of the data element values from the database into the local cache. In theory, I could simply use one or more additional AJAX calls to transfer the data from the server to the local cache. But I think there’s a better way.

I’m going to start by modifying my api.php code by adding the following lines of code.

//  read database login information and connect
require "config.php";
dbConnect();

// initialize data elements in the database if they're not already set, and
// dynamically create the javascript code to initialize the local cache
$initializeCache = initializeSCO();

Lines 2 and 3 load the database configuration information, and connect to the database. Then, line 7 calls a function in subs.php that will initialize the SCO. The value returned from the function is stored in a PHP variable called $initializeCache – I’ll talk about what it’s used for later.

Here’s my new initializeSCO() function in subs.php.

function initializeSCO() {

  global $link;
  global $SCOInstanceID;

  // has the SCO previously been initialized?
  $result = mysql_query("select count(VarName) from scormvars where (SCOInstanceID=$SCOInstanceID)",$link);
  list($count) = mysql_fetch_row($result);

  // not yet initialized - initialize all elements
  if (! $count) {

    // elements that tell the SCO which other elements are supported by this API
    initializeElement('cmi.core._children', 'student_id,student_name,lesson_location,credit,lesson_status,entry,score,total_time,exit,session_time');
    initializeElement('cmi.core.score._children','raw');

    // student information
    initializeElement('cmi.core.student_name', getFromLMS('cmi.core.student_name'));
    initializeElement('cmi.core.student_id', getFromLMS('cmi.core.student_id'));

    // test score
    initializeElement('cmi.core.score.raw', '');
    initializeElement('adlcp:masteryscore', getFromLMS('adlcp:masteryscore'));

    // SCO launch and suspend data
    initializeElement('cmi.launch_data', getFromLMS('cmi.launch_data'));
    initializeElement('cmi.suspend_data', '');

    // progress and completion tracking
    initializeElement('cmi.core.lesson_location', '');
    initializeElement('cmi.core.credit', 'credit');
    initializeElement('cmi.core.lesson_status', 'not attempted');
    initializeElement('cmi.core.entry', 'ab initio');
    initializeElement('cmi.core.exit', '');

    // seat time
    initializeElement('cmi.core.total_time', '0000:00:00');
    initializeElement('cmi.core.session_time', '');

  }

  // new session so clear pre-existing session time
  writeElement('cmi.core.session_time', '');

  // create the javascript code that will be used to set up the javascript cache 
  $initializeCache = "var cache = new Object();\n";

  $result = mysql_query("select VarName, VarValue from scormvars where (SCOInstanceID=$SCOInstanceID)", $link);
  while (list($varname, $varvalue) = mysql_fetch_row($result)) {
  
    // make the value safe by escaping quotes and special characters
    $jvarvalue = addslashes($varvalue);

    // javascript to set the initial cache value
    $initializeCache .= "cache['$varname'] = '$jvarvalue';\n";

  }

  // return javascript for cache initialization to the calling program
  return $initializeCache;

}

Here’s how it breaks down – line-by-line:

  • Lines 7 and 8 – I’m testing for whether this SCO has already been initialized in my LMS database table by counting the number of data elements corresponding to this SCOInstanceID.
     
  • Lines 11 through 40 – These lines are only executed if the SCO hasn’t yet been initialized. They’re pretty much the same as were in the initialize.php code in Rev 1, and they set the initial database values for all of the SCORM data elements that I’m supporting.
     
  • Line 43 – I clear any previous setting for the SCO session time data element.
     
  • Lines 46 through 57 – Here, I’m going to create a set of JavaScript statements that will initialize the local cache. Now, obviously, I can’t do this using directly from the subs.php code since that’s being executed on the server. But, I’ll save them into a PHP variable and return them to the calling program where they can be executed on the client side.
     

So, when called, the initializeSCO() function sets up the initial database entries (if required) and then created the JavaScript initialization code. So, in api.php, I add the following.

<?php print $initializeCache; ?>

which, will result in the student’s browser seeing something like this:

var cache = new Object();
cache['cmi.core._children'] = 'student_id,student_name,lesson_location,credit,lesson_status,entry,score,total_time,exit,session_time';
cache['cmi.core.score._children'] = 'raw';
cache['cmi.core.student_name'] = 'Addison, Steve';
cache['cmi.core.student_id'] = '007';
cache['cmi.core.score.raw'] = '';
cache['adlcp:masteryscore'] = '0';
cache['cmi.launch_data'] = '';
cache['cmi.suspend_data'] = '';
cache['cmi.core.lesson_location'] = '';
cache['cmi.core.credit'] = 'credit';
cache['cmi.core.lesson_status'] = 'not attempted';
cache['cmi.core.entry'] = 'ab initio';
cache['cmi.core.exit'] = '';
cache['cmi.core.total_time'] = '0000:00:00';
cache['cmi.core.session_time'] = '';

And, if you refer back to one of my earlier posts, you’ll see that this creates the local cache as a JavaScript object containing the initial values from the database.

Finally, I can get rid of the LMSInitialize() code, and modified form of api.php now looks like this.

<?php 

/* 

VS SCORM - JavaScript SCORM 1.2 RTE API
Rev 4.0 - Friday, November 27, 2009
Copyright (C) 2009, Addison Robson LLC

This program 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 2
of the License, or (at your option) any later version.

This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, 
Boston, MA 02110-1301, USA.

*/

//  essential functions
require "subs.php";

// input data
$SCOInstanceID = $_REQUEST['SCOInstanceID'] * 1;

//  read database login information and connect
require "config.php";
dbConnect();

// initialize data elements in the database if they're not already set, and
// dynamically create the javascript code to initialize the local cache
$initializeCache = initializeSCO();

?>
<html>
<head>
<title></title>
<script language="javascript">

// ------------------------------------------
//   Status Flags
// ------------------------------------------
var flagFinished = false;

// ------------------------------------------
//   SCO Data Cache - Initialization
// ------------------------------------------
<?php print $initializeCache; ?>

// ------------------------------------------
//   SCORM RTE Functions - Initialization
// ------------------------------------------
function LMSInitialize(dummyString) {
  return "true";
}

// ------------------------------------------
//   SCORM RTE Functions - Getting and Setting Values
// ------------------------------------------
function LMSGetValue(varname) {
  return cache[varname];
}

function LMSSetValue(varname,varvalue) {
  cache[varname] = varvalue;
  return "true";
}

// ------------------------------------------
//   SCORM RTE Functions - Saving the Cache to the Database
// ------------------------------------------
function LMSCommit(dummyString) {

  // create request object
  var req = createRequest();

  // code to prevent caching
  var d = new Date();

  // set up request parameters - uses POST method
  req.open('POST','commit.php',false);

  // create a POST-formatted list of cached data elements 
  // include only SCO-writeable data elements
  var params = 'SCOInstanceID=<?php print $SCOInstanceID; ?>&code='+d.getTime();
  params += "&data[cmi.core.lesson_location]="+urlencode(cache['cmi.core.lesson_location']);
  params += "&data[cmi.core.lesson_status]="+urlencode(cache['cmi.core.lesson_status']);
  params += "&data[cmi.core.exit]="+urlencode(cache['cmi.core.exit']);
  params += "&data[cmi.core.session_time]="+urlencode(cache['cmi.core.session_time']);
  params += "&data[cmi.core.score.raw]="+urlencode(cache['cmi.core.score.raw']);
  params += "&data[cmi.suspend_data]="+urlencode(cache['cmi.suspend_data']);

  // request headers
  req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  req.setRequestHeader("Content-length", params.length);
  req.setRequestHeader("Connection", "close");
  
  // submit to the server for processing
  req.send(params);

  // process returned data - error condition
  if (req.status != 200) {
    alert('Problem with AJAX Request in LMSCommit()');
    return "false";
  }

  // process returned data - OK
  else {
    return "true";
  }

}

// ------------------------------------------
//   SCORM RTE Functions - Closing The Session
// ------------------------------------------
function LMSFinish(dummyString) {

  // already finished - prevent repeat call
  if (flagFinished) {
    return "true";
  }

  // commit cached values to the database
  LMSCommit('');

  // create request object
  var req = createRequest();

  // code to prevent caching
  var d = new Date();

  // set up request parameters - uses GET method
  req.open('GET','finish.php?SCOInstanceID=<?php print $SCOInstanceID; ?>&code='+d.getTime(),false);

  // submit to the server for processing
  req.send(null);

  // process returned data - error condition
  if (req.status != 200) {
    alert('Problem with AJAX Request in LMSFinish()');
    return "";
  }

  // set finish flag
  flagFinished = true;

  // return to calling program
  return "true";

}

// ------------------------------------------
//   SCORM RTE Functions - Error Handling
// ------------------------------------------
function LMSGetLastError() {
  return 0;
}

function LMSGetDiagnostic(errorCode) {
  return "diagnostic string";
}

function LMSGetErrorString(errorCode) {
  return "error string";
}

// ------------------------------------------
//   AJAX Request Handling
// ------------------------------------------
function createRequest() {

  ...
  ...
  ...

}

// ------------------------------------------
//   URL Encoding
// ------------------------------------------
function urlencode( str ) {

  ...
  ...
  ...

}

</script>

</head>
<body>

&nbsp;

</body>
</html>

Note that I’ve omitted the code for the createRequest() and urlencode() functions for clarity.

Next step – give it a trial run and see what happens.

This entry was posted in Run Time Environment. Bookmark the permalink.