I want to carry a couple of basic tests within LMSSetValue and LMSGetValue to see:
- whether the specified data element is supported; and
- whether it has the necessary read or write privileges
and then set the error code appropriately. This is a pretty minimal set of tests – I’m probably going to have to add some others later – but it’s a starting point. Here’s the code.
function LMSGetValue(varname) { // not initialized or already finished if ((! flagInitialized) || (flagFinished)) { errorCode = '301'; return ''; } // not implemented if ( ! isSupported(varname) ) { errorCode = '401'; return ''; } // not readable if ( ! dataElementRead ) { errorCode = '404'; return ''; } // otherwise, return the requested data errorCode = '0'; return cache[varname]; } // -------------------------------------------------------- function LMSSetValue(varname,varvalue) { // not initialized or already finished if ((! flagInitialized) || (flagFinished)) { errorCode = '301'; return "false"; } // not implemented if ( ! isSupported(varname) ) { errorCode = '401'; return 'false'; } // not writeable if ( ! dataElementWrite ) { errorCode = '403'; return 'false'; } // otherwise, set the requested data, and return success value cache[varname] = varvalue; errorCode = '0'; return "true"; }
The additions are pretty straightforward.
- Lines 9 to 13, and 37 to 41 check to see whether the data element specified by the SCO is actually implemented (if you remember, I’m currently supporting all of the mandatory data elements, but only two of the optional elements). If the data element isn’t supported, the error code is set to ‘401’.
- Lines 15 to 19, and 43 to 47 test whether the data element is readable (for the LMSGetValue function) or writeable (for the LMSSetValue function) and, if it fails, sets error code ‘404’ or ‘403’ respecively.
Note that, if the functions are successful, the error code is set to ‘0’ before exit to indicate success. According to the SCORM RTE specification, every call to an API function must result in the error code being set – whether it’s successful or not.
Next time, I’m going to step away from the main VSSCORM code and do some work on a test harness that will allow me to monitor the SCO-LMS communications in order to make sure that all of this is working.
You might want to take a look at this test wrapper:
http://pipwerks.com/2008/01/16/a-revised-scorm-api-wrapper/
I haven’t looked at this version, but he says that it is based on Claude Ostyn’s original code, which I have used. Too bad that Claude’s site is gone now. At one point I have archived off his site, but I’m not sure where it is now…
Thank you, Joe. I will certainly look into this.
Thanks Steve for a great series of posts. Very educational. I’ve been able to set up an example using your rte and with some tweaks able to get scores and completion data back from a Captivate course. One issue I am running into now is that if a user passes a course but then later comes back to review it, the “passed” and raw scores get overwritten when the course is launched again. I’ve combed through the SCORM 1.2 documentation and found mentions of cmi.core.credit needing to be set to “no-credit” as well as cmi.core.lesson_mode set to “review” and have modified my code to change the varvalues in the scormvars table for both of these elements before launching the course but the course still overwrites the cmi.core.lesson_status to failed and cmi.core.score.raw when it’s launched. Any ideas on why the course still overwrites the values and potential workarounds?
Steve, This is an excellent working model for LMS SCORM compliance. I liked all the material you provided here. I had been searching for some starting point for making an LMS SCORM compliant and found your blog and since then hooked on to it.
A small thing I noted….the variables ‘dataElementRead’ and ‘dataElementWrite’ that you are setting in the function ‘isSupported’ are not declared anywhere in api.php…(may be i missed that)… I think the ideal place would be:
// Status Flags
var flagFinished = false;
var flagInitialized = false;
var errorCode = ‘0’;
var dataElementRead = ”;
var dataElementWrite = ”;
Thanks, Suresh.
I actually declared them in function isSupported(dataElementName) – see http://www.vsscorm.net/2011/09/06/step-60-supported-data-elements/. But you’re probably right – they should be declared in a more obvious place since they’re global variables – not just local to the function.
Steve, love the work you’ve put in so far. It’s going to save us a mountain of time getting our LMS SCORM compliant. First off I want to extend an offering, if there is anything you need to keep the project moving forward let me know. Second, I am curious.. How come these code changes don’t make it in the downloadable release?
There appears to be a discrepancy in terms of the error codes. A complete list of errors including their meaning can be found at:
http://scorm.com/scorm-explained/technical-scorm/run-time/run-time-reference/
From the document is seams like we need to expand the above such that for example in the LMSGetValue function:
if (! flagInitialized) errorCode = ‘122’;
if (flagFinished) errorCode =’123′;
etc..
How sticky do you think these SCOs are in terms of the error codes defined in the spec?
Disregard my last.. I was looking at SCORM 2004.
My bad!!!
Thanks Steve
Thanks a lot for great article, the entire article was very informative, I am unknown to PHP and was required to develop LMS in asp.net, i read a lot of example but was not able to code in my LMS.
I took a entire day to read your all the page and followed the sample and converted the code to asp.net and finally was able to code LMS with scrom.
Thanks a lot.
Fantastic tutorial, really easy to follow and still relevant 7 years on!
Thanks a lot