"Fossies" - the Fresh Open Source Software Archive

Member "moodle/mod/scorm/classes/external.php" (6 Sep 2019, 39148 Bytes) of package /linux/www/moodle-3.6.6.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "external.php" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.6.5_vs_3.6.6.

    1 <?php
    2 // This file is part of Moodle - http://moodle.org/
    3 //
    4 // Moodle is free software: you can redistribute it and/or modify
    5 // it under the terms of the GNU General Public License as published by
    6 // the Free Software Foundation, either version 3 of the License, or
    7 // (at your option) any later version.
    8 //
    9 // Moodle is distributed in the hope that it will be useful,
   10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
   11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12 // GNU General Public License for more details.
   13 //
   14 // You should have received a copy of the GNU General Public License
   15 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
   16 
   17 /**
   18  * SCORM module external API
   19  *
   20  * @package    mod_scorm
   21  * @category   external
   22  * @copyright  2015 Juan Leyva <juan@moodle.com>
   23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
   24  * @since      Moodle 3.0
   25  */
   26 
   27 defined('MOODLE_INTERNAL') || die;
   28 
   29 require_once($CFG->libdir . '/externallib.php');
   30 require_once($CFG->dirroot . '/mod/scorm/lib.php');
   31 require_once($CFG->dirroot . '/mod/scorm/locallib.php');
   32 
   33 /**
   34  * SCORM module external functions
   35  *
   36  * @package    mod_scorm
   37  * @category   external
   38  * @copyright  2015 Juan Leyva <juan@moodle.com>
   39  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
   40  * @since      Moodle 3.0
   41  */
   42 class mod_scorm_external extends external_api {
   43 
   44     /**
   45      * Returns description of method parameters
   46      *
   47      * @return external_function_parameters
   48      * @since Moodle 3.0
   49      */
   50     public static function view_scorm_parameters() {
   51         return new external_function_parameters(
   52             array(
   53                 'scormid' => new external_value(PARAM_INT, 'scorm instance id')
   54             )
   55         );
   56     }
   57 
   58     /**
   59      * Trigger the course module viewed event.
   60      *
   61      * @param int $scormid the scorm instance id
   62      * @return array of warnings and status result
   63      * @since Moodle 3.0
   64      * @throws moodle_exception
   65      */
   66     public static function view_scorm($scormid) {
   67         global $DB, $CFG;
   68         require_once($CFG->dirroot . '/mod/scorm/lib.php');
   69 
   70         $params = self::validate_parameters(self::view_scorm_parameters(),
   71                                             array(
   72                                                 'scormid' => $scormid
   73                                             ));
   74         $warnings = array();
   75 
   76         // Request and permission validation.
   77         $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST);
   78         list($course, $cm) = get_course_and_cm_from_instance($scorm, 'scorm');
   79 
   80         $context = context_module::instance($cm->id);
   81         self::validate_context($context);
   82 
   83         // Call the scorm/lib API.
   84         scorm_view($scorm, $course, $cm, $context);
   85 
   86         $result = array();
   87         $result['status'] = true;
   88         $result['warnings'] = $warnings;
   89         return $result;
   90     }
   91 
   92     /**
   93      * Returns description of method result value
   94      *
   95      * @return external_description
   96      * @since Moodle 3.0
   97      */
   98     public static function view_scorm_returns() {
   99         return new external_single_structure(
  100             array(
  101                 'status' => new external_value(PARAM_BOOL, 'status: true if success'),
  102                 'warnings' => new external_warnings()
  103             )
  104         );
  105     }
  106 
  107     /**
  108      * Describes the parameters for get_scorm_attempt_count.
  109      *
  110      * @return external_function_parameters
  111      * @since Moodle 3.0
  112      */
  113     public static function get_scorm_attempt_count_parameters() {
  114         return new external_function_parameters(
  115             array(
  116                 'scormid' => new external_value(PARAM_INT, 'SCORM instance id'),
  117                 'userid' => new external_value(PARAM_INT, 'User id'),
  118                 'ignoremissingcompletion' => new external_value(PARAM_BOOL,
  119                                                 'Ignores attempts that haven\'t reported a grade/completion',
  120                                                 VALUE_DEFAULT, false),
  121             )
  122         );
  123     }
  124 
  125     /**
  126      * Return the number of attempts done by a user in the given SCORM.
  127      *
  128      * @param int $scormid the scorm id
  129      * @param int $userid the user id
  130      * @param bool $ignoremissingcompletion ignores attempts that haven't reported a grade/completion
  131      * @return array of warnings and the attempts count
  132      * @since Moodle 3.0
  133      */
  134     public static function get_scorm_attempt_count($scormid, $userid, $ignoremissingcompletion = false) {
  135         global $USER, $DB;
  136 
  137         $params = self::validate_parameters(self::get_scorm_attempt_count_parameters(),
  138                                             array('scormid' => $scormid, 'userid' => $userid,
  139                                                 'ignoremissingcompletion' => $ignoremissingcompletion));
  140 
  141         $attempts = array();
  142         $warnings = array();
  143 
  144         $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST);
  145         $cm = get_coursemodule_from_instance('scorm', $scorm->id);
  146 
  147         $context = context_module::instance($cm->id);
  148         self::validate_context($context);
  149 
  150         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
  151         core_user::require_active_user($user);
  152 
  153         // Extra checks so only users with permissions can view other users attempts.
  154         if ($USER->id != $user->id) {
  155             require_capability('mod/scorm:viewreport', $context);
  156         }
  157 
  158         // If the SCORM is not open this function will throw exceptions.
  159         scorm_require_available($scorm);
  160 
  161         $attemptscount = scorm_get_attempt_count($user->id, $scorm, false, $params['ignoremissingcompletion']);
  162 
  163         $result = array();
  164         $result['attemptscount'] = $attemptscount;
  165         $result['warnings'] = $warnings;
  166         return $result;
  167     }
  168 
  169     /**
  170      * Describes the get_scorm_attempt_count return value.
  171      *
  172      * @return external_single_structure
  173      * @since Moodle 3.0
  174      */
  175     public static function get_scorm_attempt_count_returns() {
  176 
  177         return new external_single_structure(
  178             array(
  179                 'attemptscount' => new external_value(PARAM_INT, 'Attempts count'),
  180                 'warnings' => new external_warnings(),
  181             )
  182         );
  183     }
  184 
  185     /**
  186      * Describes the parameters for get_scorm_scoes.
  187      *
  188      * @return external_function_parameters
  189      * @since Moodle 3.0
  190      */
  191     public static function get_scorm_scoes_parameters() {
  192         return new external_function_parameters(
  193             array(
  194                 'scormid' => new external_value(PARAM_INT, 'scorm instance id'),
  195                 'organization' => new external_value(PARAM_RAW, 'organization id', VALUE_DEFAULT, '')
  196             )
  197         );
  198     }
  199 
  200     /**
  201      * Returns a list containing all the scoes data related to the given scorm id
  202      *
  203      * @param int $scormid the scorm id
  204      * @param string $organization the organization id
  205      * @return array warnings and the scoes data
  206      * @since Moodle 3.0
  207      */
  208     public static function get_scorm_scoes($scormid, $organization = '') {
  209         global $DB;
  210 
  211         $params = self::validate_parameters(self::get_scorm_scoes_parameters(),
  212                                             array('scormid' => $scormid, 'organization' => $organization));
  213 
  214         $scoes = array();
  215         $warnings = array();
  216 
  217         $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST);
  218         $cm = get_coursemodule_from_instance('scorm', $scorm->id);
  219 
  220         $context = context_module::instance($cm->id);
  221         self::validate_context($context);
  222 
  223         // Check settings / permissions to view the SCORM.
  224         scorm_require_available($scorm, true, $context);
  225 
  226         if (!$scoes = scorm_get_scoes($scorm->id, $params['organization'])) {
  227             // Function scorm_get_scoes return false, not an empty array.
  228             $scoes = array();
  229         } else {
  230             $scoreturnstructure = self::get_scorm_scoes_returns();
  231             foreach ($scoes as $sco) {
  232                 $extradata = array();
  233                 foreach ($sco as $element => $value) {
  234                     // Check if the element is extra data (not a basic SCO element).
  235                     if (!isset($scoreturnstructure->keys['scoes']->content->keys[$element])) {
  236                         $extradata[] = array(
  237                             'element' => $element,
  238                             'value' => $value
  239                         );
  240                     }
  241                 }
  242                 $sco->extradata = $extradata;
  243             }
  244         }
  245 
  246         $result = array();
  247         $result['scoes'] = $scoes;
  248         $result['warnings'] = $warnings;
  249         return $result;
  250     }
  251 
  252     /**
  253      * Describes the get_scorm_scoes return value.
  254      *
  255      * @return external_single_structure
  256      * @since Moodle 3.0
  257      */
  258     public static function get_scorm_scoes_returns() {
  259 
  260         return new external_single_structure(
  261             array(
  262                 'scoes' => new external_multiple_structure(
  263                     new external_single_structure(
  264                         array(
  265                             'id' => new external_value(PARAM_INT, 'sco id'),
  266                             'scorm' => new external_value(PARAM_INT, 'scorm id'),
  267                             'manifest' => new external_value(PARAM_NOTAGS, 'manifest id'),
  268                             'organization' => new external_value(PARAM_NOTAGS, 'organization id'),
  269                             'parent' => new external_value(PARAM_NOTAGS, 'parent'),
  270                             'identifier' => new external_value(PARAM_NOTAGS, 'identifier'),
  271                             'launch' => new external_value(PARAM_NOTAGS, 'launch file'),
  272                             'scormtype' => new external_value(PARAM_ALPHA, 'scorm type (asset, sco)'),
  273                             'title' => new external_value(PARAM_NOTAGS, 'sco title'),
  274                             'sortorder' => new external_value(PARAM_INT, 'sort order'),
  275                             'extradata' => new external_multiple_structure(
  276                                 new external_single_structure(
  277                                     array(
  278                                         'element' => new external_value(PARAM_RAW, 'element name'),
  279                                         'value' => new external_value(PARAM_RAW, 'element value')
  280                                     )
  281                                 ), 'Additional SCO data', VALUE_OPTIONAL
  282                             )
  283                         ), 'SCORM SCO data'
  284                     )
  285                 ),
  286                 'warnings' => new external_warnings(),
  287             )
  288         );
  289     }
  290 
  291     /**
  292      * Describes the parameters for get_scorm_user_data.
  293      *
  294      * @return external_function_parameters
  295      * @since Moodle 3.0
  296      */
  297     public static function get_scorm_user_data_parameters() {
  298         return new external_function_parameters(
  299             array(
  300                 'scormid' => new external_value(PARAM_INT, 'scorm instance id'),
  301                 'attempt' => new external_value(PARAM_INT, 'attempt number')
  302             )
  303         );
  304     }
  305 
  306     /**
  307      * Retrieves user tracking and SCO data and default SCORM values
  308      *
  309      * @param int $scormid the scorm id
  310      * @param int $attempt the attempt number
  311      * @return array warnings and the scoes data
  312      * @throws  moodle_exception
  313      * @since Moodle 3.0
  314      */
  315     public static function get_scorm_user_data($scormid, $attempt) {
  316         global $CFG, $DB;
  317 
  318         $params = self::validate_parameters(self::get_scorm_user_data_parameters(),
  319                                             array('scormid' => $scormid, 'attempt' => $attempt));
  320 
  321         $data = array();
  322         $warnings = array();
  323 
  324         $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST);
  325         $cm = get_coursemodule_from_instance('scorm', $scorm->id);
  326 
  327         $context = context_module::instance($cm->id);
  328         self::validate_context($context);
  329 
  330         scorm_require_available($scorm, true, $context);
  331 
  332         $scorm->version = strtolower(clean_param($scorm->version, PARAM_SAFEDIR));
  333         if (!file_exists($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'lib.php')) {
  334             $scorm->version = 'scorm_12';
  335         }
  336         require_once($CFG->dirroot.'/mod/scorm/datamodels/'.$scorm->version.'lib.php');
  337 
  338         if ($scoes = scorm_get_scoes($scorm->id)) {
  339             $def = new stdClass();
  340             $user = new stdClass();
  341 
  342             foreach ($scoes as $sco) {
  343                 $def->{$sco->id} = new stdClass();
  344                 $user->{$sco->id} = new stdClass();
  345                 // We force mode normal, this can be override by the client at any time.
  346                 $def->{$sco->id} = get_scorm_default($user->{$sco->id}, $scorm, $sco->id, $params['attempt'], 'normal');
  347 
  348                 $userdata = array();
  349                 $defaultdata = array();
  350 
  351                 foreach ((array) $user->{$sco->id} as $key => $val) {
  352                     $userdata[] = array(
  353                         'element' => $key,
  354                         'value' => $val
  355                     );
  356                 }
  357                 foreach ($def->{$sco->id} as $key => $val) {
  358                     $defaultdata[] = array(
  359                         'element' => $key,
  360                         'value' => $val
  361                     );
  362                 }
  363 
  364                 $data[] = array(
  365                     'scoid' => $sco->id,
  366                     'userdata' => $userdata,
  367                     'defaultdata' => $defaultdata,
  368                 );
  369             }
  370         }
  371 
  372         $result = array();
  373         $result['data'] = $data;
  374         $result['warnings'] = $warnings;
  375         return $result;
  376     }
  377 
  378     /**
  379      * Describes the get_scorm_user_data return value.
  380      *
  381      * @return external_single_structure
  382      * @since Moodle 3.0
  383      */
  384     public static function get_scorm_user_data_returns() {
  385 
  386         return new external_single_structure(
  387             array(
  388                 'data' => new external_multiple_structure(
  389                     new external_single_structure(
  390                         array(
  391                             'scoid' => new external_value(PARAM_INT, 'sco id'),
  392                             'userdata' => new external_multiple_structure(
  393                                             new external_single_structure(
  394                                                 array(
  395                                                     'element' => new external_value(PARAM_RAW, 'element name'),
  396                                                     'value' => new external_value(PARAM_RAW, 'element value')
  397                                                 )
  398                                             )
  399                                           ),
  400                             'defaultdata' => new external_multiple_structure(
  401                                                 new external_single_structure(
  402                                                     array(
  403                                                         'element' => new external_value(PARAM_RAW, 'element name'),
  404                                                         'value' => new external_value(PARAM_RAW, 'element value')
  405                                                     )
  406                                                 )
  407                                              ),
  408                         ), 'SCO data'
  409                     )
  410                 ),
  411                 'warnings' => new external_warnings(),
  412             )
  413         );
  414     }
  415 
  416     /**
  417      * Describes the parameters for insert_scorm_tracks.
  418      *
  419      * @return external_function_parameters
  420      * @since Moodle 3.0
  421      */
  422     public static function insert_scorm_tracks_parameters() {
  423         return new external_function_parameters(
  424             array(
  425                 'scoid' => new external_value(PARAM_INT, 'SCO id'),
  426                 'attempt' => new external_value(PARAM_INT, 'attempt number'),
  427                 'tracks' => new external_multiple_structure(
  428                     new external_single_structure(
  429                         array(
  430                             'element' => new external_value(PARAM_RAW, 'element name'),
  431                             'value' => new external_value(PARAM_RAW, 'element value')
  432                         )
  433                     )
  434                 ),
  435             )
  436         );
  437     }
  438 
  439     /**
  440      * Saves a SCORM tracking record.
  441      * It will overwrite any existing tracking data for this attempt.
  442      * Validation should be performed before running the function to ensure the user will not lose any existing attempt data.
  443      *
  444      * @param int $scoid the SCO id
  445      * @param string $attempt the attempt number
  446      * @param array $tracks the track records to be stored
  447      * @return array warnings and the scoes data
  448      * @throws moodle_exception
  449      * @since Moodle 3.0
  450      */
  451     public static function insert_scorm_tracks($scoid, $attempt, $tracks) {
  452         global $USER, $DB;
  453 
  454         $params = self::validate_parameters(self::insert_scorm_tracks_parameters(),
  455                                             array('scoid' => $scoid, 'attempt' => $attempt, 'tracks' => $tracks));
  456 
  457         $trackids = array();
  458         $warnings = array();
  459 
  460         $sco = scorm_get_sco($params['scoid'], SCO_ONLY);
  461         if (!$sco) {
  462             throw new moodle_exception('cannotfindsco', 'scorm');
  463         }
  464 
  465         $scorm = $DB->get_record('scorm', array('id' => $sco->scorm), '*', MUST_EXIST);
  466         $cm = get_coursemodule_from_instance('scorm', $scorm->id);
  467 
  468         $context = context_module::instance($cm->id);
  469         self::validate_context($context);
  470 
  471         // Check settings / permissions to view the SCORM.
  472         require_capability('mod/scorm:savetrack', $context);
  473 
  474         // Check settings / permissions to view the SCORM.
  475         scorm_require_available($scorm);
  476 
  477         foreach ($params['tracks'] as $track) {
  478             $element = $track['element'];
  479             $value = $track['value'];
  480             $trackid = scorm_insert_track($USER->id, $scorm->id, $sco->id, $params['attempt'], $element, $value,
  481                                             $scorm->forcecompleted);
  482 
  483             if ($trackid) {
  484                 $trackids[] = $trackid;
  485             } else {
  486                 $warnings[] = array(
  487                     'item' => 'scorm',
  488                     'itemid' => $scorm->id,
  489                     'warningcode' => 1,
  490                     'message' => 'Element: ' . $element . ' was not saved'
  491                 );
  492             }
  493         }
  494 
  495         $result = array();
  496         $result['trackids'] = $trackids;
  497         $result['warnings'] = $warnings;
  498         return $result;
  499     }
  500 
  501     /**
  502      * Describes the insert_scorm_tracks return value.
  503      *
  504      * @return external_single_structure
  505      * @since Moodle 3.0
  506      */
  507     public static function insert_scorm_tracks_returns() {
  508 
  509         return new external_single_structure(
  510             array(
  511                 'trackids' => new external_multiple_structure(new external_value(PARAM_INT, 'track id')),
  512                 'warnings' => new external_warnings(),
  513             )
  514         );
  515     }
  516 
  517     /**
  518      * Describes the parameters for get_scorm_sco_tracks.
  519      *
  520      * @return external_function_parameters
  521      * @since Moodle 3.0
  522      */
  523     public static function get_scorm_sco_tracks_parameters() {
  524         return new external_function_parameters(
  525             array(
  526                 'scoid' => new external_value(PARAM_INT, 'sco id'),
  527                 'userid' => new external_value(PARAM_INT, 'user id'),
  528                 'attempt' => new external_value(PARAM_INT, 'attempt number (0 for last attempt)', VALUE_DEFAULT, 0)
  529             )
  530         );
  531     }
  532 
  533     /**
  534      * Retrieves SCO tracking data for the given user id and attempt number
  535      *
  536      * @param int $scoid the sco id
  537      * @param int $userid the user id
  538      * @param int $attempt the attempt number
  539      * @return array warnings and the scoes data
  540      * @since Moodle 3.0
  541      */
  542     public static function get_scorm_sco_tracks($scoid, $userid, $attempt = 0) {
  543         global $USER, $DB;
  544 
  545         $params = self::validate_parameters(self::get_scorm_sco_tracks_parameters(),
  546                                             array('scoid' => $scoid, 'userid' => $userid, 'attempt' => $attempt));
  547 
  548         $tracks = array();
  549         $warnings = array();
  550 
  551         $sco = scorm_get_sco($params['scoid'], SCO_ONLY);
  552         if (!$sco) {
  553             throw new moodle_exception('cannotfindsco', 'scorm');
  554         }
  555 
  556         $scorm = $DB->get_record('scorm', array('id' => $sco->scorm), '*', MUST_EXIST);
  557         $cm = get_coursemodule_from_instance('scorm', $scorm->id);
  558 
  559         $context = context_module::instance($cm->id);
  560         self::validate_context($context);
  561 
  562         $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
  563         core_user::require_active_user($user);
  564 
  565         // Extra checks so only users with permissions can view other users attempts.
  566         if ($USER->id != $user->id) {
  567             require_capability('mod/scorm:viewreport', $context);
  568         }
  569 
  570         scorm_require_available($scorm, true, $context);
  571 
  572         if (empty($params['attempt'])) {
  573             $params['attempt'] = scorm_get_last_attempt($scorm->id, $user->id);
  574         }
  575 
  576         $attempted = false;
  577         if ($scormtracks = scorm_get_tracks($sco->id, $params['userid'], $params['attempt'])) {
  578             // Check if attempted.
  579             if ($scormtracks->status != '') {
  580                 $attempted = true;
  581                 foreach ($scormtracks as $element => $value) {
  582                     $tracks[] = array(
  583                         'element' => $element,
  584                         'value' => $value,
  585                     );
  586                 }
  587             }
  588         }
  589 
  590         if (!$attempted) {
  591             $warnings[] = array(
  592                 'item' => 'attempt',
  593                 'itemid' => $params['attempt'],
  594                 'warningcode' => 'notattempted',
  595                 'message' => get_string('notattempted', 'scorm')
  596             );
  597         }
  598 
  599         $result = array();
  600         $result['data']['attempt'] = $params['attempt'];
  601         $result['data']['tracks'] = $tracks;
  602         $result['warnings'] = $warnings;
  603         return $result;
  604     }
  605 
  606     /**
  607      * Describes the get_scorm_sco_tracks return value.
  608      *
  609      * @return external_single_structure
  610      * @since Moodle 3.0
  611      */
  612     public static function get_scorm_sco_tracks_returns() {
  613 
  614         return new external_single_structure(
  615             array(
  616                 'data' => new external_single_structure(
  617                     array(
  618                         'attempt' => new external_value(PARAM_INT, 'Attempt number'),
  619                         'tracks' => new external_multiple_structure(
  620                             new external_single_structure(
  621                                 array(
  622                                     'element' => new external_value(PARAM_RAW, 'Element name'),
  623                                     'value' => new external_value(PARAM_RAW, 'Element value')
  624                                 ), 'Tracks data'
  625                             )
  626                         ),
  627                     ), 'SCO data'
  628                 ),
  629                 'warnings' => new external_warnings(),
  630             )
  631         );
  632     }
  633 
  634     /**
  635      * Describes the parameters for get_scorms_by_courses.
  636      *
  637      * @return external_function_parameters
  638      * @since Moodle 3.0
  639      */
  640     public static function get_scorms_by_courses_parameters() {
  641         return new external_function_parameters (
  642             array(
  643                 'courseids' => new external_multiple_structure(
  644                     new external_value(PARAM_INT, 'course id'), 'Array of course ids', VALUE_DEFAULT, array()
  645                 ),
  646             )
  647         );
  648     }
  649 
  650     /**
  651      * Returns a list of scorms in a provided list of courses,
  652      * if no list is provided all scorms that the user can view will be returned.
  653      *
  654      * @param array $courseids the course ids
  655      * @return array the scorm details
  656      * @since Moodle 3.0
  657      */
  658     public static function get_scorms_by_courses($courseids = array()) {
  659         global $CFG;
  660 
  661         $returnedscorms = array();
  662         $warnings = array();
  663 
  664         $params = self::validate_parameters(self::get_scorms_by_courses_parameters(), array('courseids' => $courseids));
  665 
  666         $courses = array();
  667         if (empty($params['courseids'])) {
  668             $courses = enrol_get_my_courses();
  669             $params['courseids'] = array_keys($courses);
  670         }
  671 
  672         // Ensure there are courseids to loop through.
  673         if (!empty($params['courseids'])) {
  674 
  675             list($courses, $warnings) = external_util::validate_courses($params['courseids'], $courses);
  676 
  677             // Get the scorms in this course, this function checks users visibility permissions.
  678             // We can avoid then additional validate_context calls.
  679             $scorms = get_all_instances_in_courses("scorm", $courses);
  680 
  681             $fs = get_file_storage();
  682             foreach ($scorms as $scorm) {
  683 
  684                 $context = context_module::instance($scorm->coursemodule);
  685 
  686                 // Entry to return.
  687                 $module = array();
  688 
  689                 // First, we return information that any user can see in (or can deduce from) the web interface.
  690                 $module['id'] = $scorm->id;
  691                 $module['coursemodule'] = $scorm->coursemodule;
  692                 $module['course'] = $scorm->course;
  693                 $module['name']  = external_format_string($scorm->name, $context->id);
  694                 list($module['intro'], $module['introformat']) =
  695                     external_format_text($scorm->intro, $scorm->introformat, $context->id, 'mod_scorm', 'intro', null);
  696                 $module['introfiles'] = external_util::get_area_files($context->id, 'mod_scorm', 'intro', false, false);
  697 
  698                 // Check if the SCORM open and return warnings if so.
  699                 list($open, $openwarnings) = scorm_get_availability_status($scorm, true, $context);
  700 
  701                 if (!$open) {
  702                     foreach ($openwarnings as $warningkey => $warningdata) {
  703                         $warnings[] = array(
  704                             'item' => 'scorm',
  705                             'itemid' => $scorm->id,
  706                             'warningcode' => $warningkey,
  707                             'message' => get_string($warningkey, 'scorm', $warningdata)
  708                         );
  709                     }
  710                 } else {
  711                     $module['packagesize'] = 0;
  712                     // SCORM size.
  713                     if ($scorm->scormtype === SCORM_TYPE_LOCAL or $scorm->scormtype === SCORM_TYPE_LOCALSYNC) {
  714                         if ($packagefile = $fs->get_file($context->id, 'mod_scorm', 'package', 0, '/', $scorm->reference)) {
  715                             $module['packagesize'] = $packagefile->get_filesize();
  716                             // Download URL.
  717                             $module['packageurl'] = moodle_url::make_webservice_pluginfile_url(
  718                                                     $context->id, 'mod_scorm', 'package', 0, '/', $scorm->reference)->out(false);
  719                         }
  720                     }
  721 
  722                     $module['protectpackagedownloads'] = get_config('scorm', 'protectpackagedownloads');
  723 
  724                     $viewablefields = array('version', 'maxgrade', 'grademethod', 'whatgrade', 'maxattempt', 'forcecompleted',
  725                                             'forcenewattempt', 'lastattemptlock', 'displayattemptstatus', 'displaycoursestructure',
  726                                             'sha1hash', 'md5hash', 'revision', 'launch', 'skipview', 'hidebrowse', 'hidetoc', 'nav',
  727                                             'navpositionleft', 'navpositiontop', 'auto', 'popup', 'width', 'height', 'timeopen',
  728                                             'timeclose', 'displayactivityname', 'scormtype', 'reference');
  729 
  730                     // Check additional permissions for returning optional private settings.
  731                     if (has_capability('moodle/course:manageactivities', $context)) {
  732 
  733                         $additionalfields = array('updatefreq', 'options', 'completionstatusrequired', 'completionscorerequired',
  734                                                   'completionstatusallscos', 'autocommit', 'timemodified', 'section', 'visible',
  735                                                   'groupmode', 'groupingid');
  736                         $viewablefields = array_merge($viewablefields, $additionalfields);
  737 
  738                     }
  739 
  740                     foreach ($viewablefields as $field) {
  741                         $module[$field] = $scorm->{$field};
  742                     }
  743                 }
  744 
  745                 $returnedscorms[] = $module;
  746             }
  747         }
  748 
  749         $result = array();
  750         $result['scorms'] = $returnedscorms;
  751         $result['warnings'] = $warnings;
  752         return $result;
  753     }
  754 
  755     /**
  756      * Describes the get_scorms_by_courses return value.
  757      *
  758      * @return external_single_structure
  759      * @since Moodle 3.0
  760      */
  761     public static function get_scorms_by_courses_returns() {
  762 
  763         return new external_single_structure(
  764             array(
  765                 'scorms' => new external_multiple_structure(
  766                     new external_single_structure(
  767                         array(
  768                             'id' => new external_value(PARAM_INT, 'SCORM id'),
  769                             'coursemodule' => new external_value(PARAM_INT, 'Course module id'),
  770                             'course' => new external_value(PARAM_INT, 'Course id'),
  771                             'name' => new external_value(PARAM_RAW, 'SCORM name'),
  772                             'intro' => new external_value(PARAM_RAW, 'The SCORM intro'),
  773                             'introformat' => new external_format_value('intro'),
  774                             'introfiles' => new external_files('Files in the introduction text', VALUE_OPTIONAL),
  775                             'packagesize' => new external_value(PARAM_INT, 'SCORM zip package size', VALUE_OPTIONAL),
  776                             'packageurl' => new external_value(PARAM_URL, 'SCORM zip package URL', VALUE_OPTIONAL),
  777                             'version' => new external_value(PARAM_NOTAGS, 'SCORM version (SCORM_12, SCORM_13, SCORM_AICC)',
  778                                                             VALUE_OPTIONAL),
  779                             'maxgrade' => new external_value(PARAM_INT, 'Max grade', VALUE_OPTIONAL),
  780                             'grademethod' => new external_value(PARAM_INT, 'Grade method', VALUE_OPTIONAL),
  781                             'whatgrade' => new external_value(PARAM_INT, 'What grade', VALUE_OPTIONAL),
  782                             'maxattempt' => new external_value(PARAM_INT, 'Maximum number of attemtps', VALUE_OPTIONAL),
  783                             'forcecompleted' => new external_value(PARAM_BOOL, 'Status current attempt is forced to "completed"',
  784                                                                     VALUE_OPTIONAL),
  785                             'forcenewattempt' => new external_value(PARAM_INT, 'Controls re-entry behaviour',
  786                                                                     VALUE_OPTIONAL),
  787                             'lastattemptlock' => new external_value(PARAM_BOOL, 'Prevents to launch new attempts once finished',
  788                                                                     VALUE_OPTIONAL),
  789                             'displayattemptstatus' => new external_value(PARAM_INT, 'How to display attempt status',
  790                                                                             VALUE_OPTIONAL),
  791                             'displaycoursestructure' => new external_value(PARAM_BOOL, 'Display contents structure',
  792                                                                             VALUE_OPTIONAL),
  793                             'sha1hash' => new external_value(PARAM_NOTAGS, 'Package content or ext path hash', VALUE_OPTIONAL),
  794                             'md5hash' => new external_value(PARAM_NOTAGS, 'MD5 Hash of package file', VALUE_OPTIONAL),
  795                             'revision' => new external_value(PARAM_INT, 'Revison number', VALUE_OPTIONAL),
  796                             'launch' => new external_value(PARAM_INT, 'First content to launch', VALUE_OPTIONAL),
  797                             'skipview' => new external_value(PARAM_INT, 'How to skip the content structure page', VALUE_OPTIONAL),
  798                             'hidebrowse' => new external_value(PARAM_BOOL, 'Disable preview mode?', VALUE_OPTIONAL),
  799                             'hidetoc' => new external_value(PARAM_INT, 'How to display the SCORM structure in player',
  800                                                             VALUE_OPTIONAL),
  801                             'nav' => new external_value(PARAM_INT, 'Show navigation buttons', VALUE_OPTIONAL),
  802                             'navpositionleft' => new external_value(PARAM_INT, 'Navigation position left', VALUE_OPTIONAL),
  803                             'navpositiontop' => new external_value(PARAM_INT, 'Navigation position top', VALUE_OPTIONAL),
  804                             'auto' => new external_value(PARAM_BOOL, 'Auto continue?', VALUE_OPTIONAL),
  805                             'popup' => new external_value(PARAM_INT, 'Display in current or new window', VALUE_OPTIONAL),
  806                             'width' => new external_value(PARAM_INT, 'Frame width', VALUE_OPTIONAL),
  807                             'height' => new external_value(PARAM_INT, 'Frame height', VALUE_OPTIONAL),
  808                             'timeopen' => new external_value(PARAM_INT, 'Available from', VALUE_OPTIONAL),
  809                             'timeclose' => new external_value(PARAM_INT, 'Available to', VALUE_OPTIONAL),
  810                             'displayactivityname' => new external_value(PARAM_BOOL, 'Display the activity name above the player?',
  811                                                                         VALUE_OPTIONAL),
  812                             'scormtype' => new external_value(PARAM_ALPHA, 'SCORM type', VALUE_OPTIONAL),
  813                             'reference' => new external_value(PARAM_NOTAGS, 'Reference to the package', VALUE_OPTIONAL),
  814                             'protectpackagedownloads' => new external_value(PARAM_BOOL, 'Protect package downloads?',
  815                                                                             VALUE_OPTIONAL),
  816                             'updatefreq' => new external_value(PARAM_INT, 'Auto-update frequency for remote packages',
  817                                                                 VALUE_OPTIONAL),
  818                             'options' => new external_value(PARAM_RAW, 'Additional options', VALUE_OPTIONAL),
  819                             'completionstatusrequired' => new external_value(PARAM_INT, 'Status passed/completed required?',
  820                                                                                 VALUE_OPTIONAL),
  821                             'completionscorerequired' => new external_value(PARAM_INT, 'Minimum score required', VALUE_OPTIONAL),
  822                             'completionstatusallscos' => new external_value(PARAM_INT, 'Require all scos to return completion status', VALUE_OPTIONAL),
  823                             'autocommit' => new external_value(PARAM_BOOL, 'Save track data automatically?', VALUE_OPTIONAL),
  824                             'timemodified' => new external_value(PARAM_INT, 'Time of last modification', VALUE_OPTIONAL),
  825                             'section' => new external_value(PARAM_INT, 'Course section id', VALUE_OPTIONAL),
  826                             'visible' => new external_value(PARAM_BOOL, 'Visible', VALUE_OPTIONAL),
  827                             'groupmode' => new external_value(PARAM_INT, 'Group mode', VALUE_OPTIONAL),
  828                             'groupingid' => new external_value(PARAM_INT, 'Group id', VALUE_OPTIONAL),
  829                         ), 'SCORM'
  830                     )
  831                 ),
  832                 'warnings' => new external_warnings(),
  833             )
  834         );
  835     }
  836 
  837     /**
  838      * Returns description of method parameters
  839      *
  840      * @return external_function_parameters
  841      * @since Moodle 3.1
  842      */
  843     public static function launch_sco_parameters() {
  844         return new external_function_parameters(
  845             array(
  846                 'scormid' => new external_value(PARAM_INT, 'SCORM instance id'),
  847                 'scoid' => new external_value(PARAM_INT, 'SCO id (empty for launching the first SCO)', VALUE_DEFAULT, 0)
  848             )
  849         );
  850     }
  851 
  852     /**
  853      * Trigger the course module viewed event.
  854      *
  855      * @param int $scormid the SCORM instance id
  856      * @param int $scoid the SCO id
  857      * @return array of warnings and status result
  858      * @since Moodle 3.1
  859      * @throws moodle_exception
  860      */
  861     public static function launch_sco($scormid, $scoid = 0) {
  862         global $DB, $CFG;
  863 
  864         require_once($CFG->libdir . '/completionlib.php');
  865 
  866         $params = self::validate_parameters(self::launch_sco_parameters(),
  867                                             array(
  868                                                 'scormid' => $scormid,
  869                                                 'scoid' => $scoid
  870                                             ));
  871         $warnings = array();
  872 
  873         // Request and permission validation.
  874         $scorm = $DB->get_record('scorm', array('id' => $params['scormid']), '*', MUST_EXIST);
  875         list($course, $cm) = get_course_and_cm_from_instance($scorm, 'scorm');
  876 
  877         $context = context_module::instance($cm->id);
  878         self::validate_context($context);
  879 
  880         // If the SCORM is not open this function will throw exceptions.
  881         scorm_require_available($scorm);
  882 
  883         if (!empty($params['scoid']) and !($sco = scorm_get_sco($params['scoid'], SCO_ONLY))) {
  884             throw new moodle_exception('cannotfindsco', 'scorm');
  885         }
  886 
  887         // Mark module viewed.
  888         $completion = new completion_info($course);
  889         $completion->set_module_viewed($cm);
  890 
  891         list($sco, $scolaunchurl) = scorm_get_sco_and_launch_url($scorm, $params['scoid'], $context);
  892         // Trigger the SCO launched event.
  893         scorm_launch_sco($scorm, $sco, $cm, $context, $scolaunchurl);
  894 
  895         $result = array();
  896         $result['status'] = true;
  897         $result['warnings'] = $warnings;
  898         return $result;
  899     }
  900 
  901     /**
  902      * Returns description of method result value
  903      *
  904      * @return external_description
  905      * @since Moodle 3.1
  906      */
  907     public static function launch_sco_returns() {
  908         return new external_single_structure(
  909             array(
  910                 'status' => new external_value(PARAM_BOOL, 'status: true if success'),
  911                 'warnings' => new external_warnings()
  912             )
  913         );
  914     }
  915 }