Uploaded image for project: 'Moodle'
  1. Moodle
  2. MDL-46222

SCORM package caching

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Open
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: 2.7
    • Fix Version/s: DEV backlog
    • Component/s: SCORM
    • Labels:
    • Affected Branches:
      MOODLE_27_STABLE

      Description

      Currently, mod_scorm downloads the packages every time if set on "Downloaded package" with Auto-update frequency on "Every day" or "Every time it's used", irregardless of caching informations. I've made a little patch which saves the ETag and Last-Modified informations in order not to download the package again if it has not been modified.

      I'm not completely sure this is the right place where to place this patch (against trunk 2.7), but here it is:

      diff -Naur /home/mattia/moodle-2.7/mod/scorm/db/install.xml ./db/install.xml
      --- /home/mattia/moodle-2.7/mod/scorm/db/install.xml	2014-06-26 10:35:58.000000000 +0200
      +++ ./db/install.xml	2014-07-01 16:18:11.654239191 +0200
      @@ -45,6 +45,8 @@
               <FIELD NAME="completionstatusrequired" TYPE="int" LENGTH="1" NOTNULL="false" SEQUENCE="false"/>
               <FIELD NAME="completionscorerequired" TYPE="int" LENGTH="2" NOTNULL="false" SEQUENCE="false"/>
               <FIELD NAME="displayactivityname" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="1" SEQUENCE="false"/>
      +        <FIELD NAME="etag" TYPE="char" LENGTH="64" NOTNULL="false" SEQUENCE="false" COMMENT="Last ETag received from the download server."/>
      +        <FIELD NAME="lastmodified" TYPE="int" LENGTH="11" NOTNULL="false" SEQUENCE="false" COMMENT="Last-Modified header received from the download server."/>
             </FIELDS>
             <KEYS>
               <KEY NAME="primary" TYPE="primary" FIELDS="id"/>
      @@ -222,4 +224,4 @@
             </KEYS>
           </TABLE>
         </TABLES>
      -</XMLDB>
      \ No newline at end of file
      +</XMLDB>
      diff -Naur /home/mattia/moodle-2.7/mod/scorm/db/upgrade.php ./db/upgrade.php
      --- /home/mattia/moodle-2.7/mod/scorm/db/upgrade.php	2014-06-26 10:35:58.000000000 +0200
      +++ ./db/upgrade.php	2014-07-01 16:23:40.698226590 +0200
      @@ -279,6 +279,29 @@
           // Moodle v2.7.0 release upgrade line.
           // Put any upgrade step following this.
       
      +    if ($oldversion < 2014062501) {
      +
      +        // Define field id to be added to scorm.
      +        $table = new xmldb_table('scorm');
      +        $field = new xmldb_field('etag', XMLDB_TYPE_CHAR, '64', null, null, null, null, 'completionscorerequired');
      +
      +        // Conditionally launch add field id.
      +        if (!$dbman->field_exists($table, $field)) {
      +            $dbman->add_field($table, $field);
      +        }
      +
      +        $field = new xmldb_field('lastmodified', XMLDB_TYPE_INTEGER, '11', null, null, null, null, 'etag');
      +
      +        // Conditionally launch add field lastmodified.
      +        if (!$dbman->field_exists($table, $field)) {
      +            $dbman->add_field($table, $field);
      +        }
      +
      +        // Scorm savepoint reached.
      +        upgrade_mod_savepoint(true, 2014062501, 'scorm');
      +    }
      +
      +
           return true;
       }
       
      diff -Naur /home/mattia/moodle-2.7/mod/scorm/locallib.php ./locallib.php
      --- /home/mattia/moodle-2.7/mod/scorm/locallib.php	2014-06-26 10:35:58.000000000 +0200
      +++ ./locallib.php	2014-07-01 16:17:41.326240352 +0200
      @@ -197,6 +197,49 @@
       }
       
       /**
      + * Checks whether the scorm package must be downloaded or not, according to the ETag / Last-Modified
      + * headers. The $scorm object gets updated with the new ETag / Last-Modified.
      + *
      + * @param string $url the URL to check.
      + * @param object $scorm the scorm object containing the last ETag / Last-Modified headers.
      + */
      +function scorm_must_download($url, $scorm, $DB) {
      +    // download the headers
      +    stream_context_set_default(array('http' => array('method' => 'HEAD')));
      +    $headers = get_headers($url, 1);
      +    stream_context_set_default(array('http' => array('method' => 'GET')));
      +
      +    // get out ETag and Last-Modified
      +    $etag = null;
      +    if(array_key_exists("ETag", $headers))
      +        $etag = $headers["ETag"];
      +    $lastmodified = null;
      +    if(array_key_exists("Last-Modified", $headers)) {
      +        // get and parse Last-Modified
      +        $lastmodified_str = $headers["Last-Modified"];
      +        $d = new DateTime($lastmodified_str);
      +        $lastmodified = $d->getTimestamp();
      +    }
      +
      +    // confront with stored values
      +    $modified = true;
      +    if(!empty($etag) && !empty($scorm->etag) && $etag == $scorm->etag) {
      +        $modified = false;
      +    }
      +    if(!empty($lastmodified) && !empty($scorm->lastmodified) && $lastmodified <= $scorm->lastmodified) {
      +        $modified = false;
      +    }
      +
      +    // update scorm entry
      +    $scorm->etag = $etag;
      +    $scorm->lastmodified = $lastmodified;
      +    $DB->update_record('scorm', $scorm);
      +
      +    // return result
      +    return $modified;
      +}
      +
      +/**
        * Extracts scrom package, sets up all variables.
        * Called whenever scorm changes
        * @param object $scorm instance - fields are updated and changes saved into database
      @@ -240,7 +283,13 @@
                   if ($scorm->reference !== '' and (!$full or $scorm->sha1hash !== sha1($scorm->reference))) {
                       $fs->delete_area_files($context->id, 'mod_scorm', 'package');
                       $file_record = array('contextid'=>$context->id, 'component'=>'mod_scorm', 'filearea'=>'package', 'itemid'=>0, 'filepath'=>'/');
      -                if ($packagefile = $fs->create_file_from_url($file_record, $scorm->reference, array('calctimeout' => true))) {
      +                if (scorm_must_download($scorm->reference, $scorm, $DB)) {
      +                    add_to_log($scorm->course, 'scorm', 'update', 'view.php?id=' . $scorm->cmid, "$scorm->id", $scorm->cmid);
      +                    $packagefile = $fs->create_file_from_url($file_record, $scorm->reference, array('calctimeout' => true));
      +                } else {
      +                    $packagefile = $fs->get_file($context->id, 'mod_scorm', 'package', 0, '/', $scorm->reference);
      +                }
      +                if ($packagefile) {
                           $newhash = sha1($scorm->reference);
                       } else {
                           $newhash = null;
      diff -Naur /home/mattia/moodle-2.7/mod/scorm/version.php ./version.php
      --- /home/mattia/moodle-2.7/mod/scorm/version.php	2014-06-26 10:35:58.000000000 +0200
      +++ ./version.php	2014-07-01 16:24:13.278225342 +0200
      @@ -28,3 +28,4 @@
       $plugin->requires  = 2014050800;    // Requires this Moodle version.
       $plugin->component = 'mod_scorm';   // Full name of the plugin (used for diagnostics).
       $plugin->cron      = 300;
      +$module->version   = 2014062501;       // The current module version (Date: YYYYMMDDXX)
      

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              RedGlow Mattia Belletti
              Participants:
              Component watchers:
              Damyon Wiese, Dan Marsden, Matteo Scaramuccia, Adrian Greeve, Jake Dallimore, Mathew May, Mihail Geshoski, Peter Dias
            • Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated: