16        $this->insert = array();
 
   17        if (is_array(
$_GET[
"iL"])) {
 
   18            foreach (
$_GET[
"iL"] as $key => $value) {
 
   19                $this->insert[] = array(
"left" => $value, 
"right" => 
$_GET[
"iR"][$key]);
 
   22        if (is_array(
$_POST[
"iL"])) {
 
   23            foreach (
$_POST[
"iL"] as $key => $value) {
 
   24                $this->insert[] = array(
"left" => $value, 
"right" => 
$_POST[
"iR"][$key]);
 
   28        $this->update = array();
 
   29        if (is_array(
$_GET[
"uL"])) {
 
   30            foreach (
$_GET[
"uL"] as $key => $value) {
 
   31                $this->update[] = array(
"left" => $value, 
"right" => 
$_GET[
"uR"][$key]);
 
   34        if (is_array(
$_POST[
"uL"])) {
 
   35            foreach (
$_POST[
"uL"] as $key => $value) {
 
   36                $this->update[] = array(
"left" => $value, 
"right" => 
$_POST[
"uR"][$key]);
 
   41    public function store($obj_id = 0, $sahs_id = 0, $extractData = 1)
 
   47        $ref_id = 
$_GET[
"ref_id"];
 
   53        $f = fopen(
"./Modules/ScormAicc/log/scorm.log", 
"a");
 
   54        fwrite(
$f, 
"\nCALLING SCORM store()\n");
 
   55        fwrite(
$f, 
'POST: ' . print_r(
$_POST, 
true));
 
   58        if (empty($sahs_id)) {
 
   62        if ($extractData == 1) {
 
   73            fwrite(
$f, 
"Error: No obj_id given.\n");
 
   75            foreach ($this->insert as $insert) {
 
   78                                SELECT * FROM scorm_tracking  
   83                    array(
'integer',
'integer',
'text',
'integer'),
 
   84                    array($user_id,$sahs_id,$insert[
"left"],$obj_id)
 
   86                if ($rec = 
$ilDB->fetchAssoc($set)) {
 
   87                    fwrite(
$f, 
"Error Insert, left value already exists. L:" . $insert[
"left"] . 
",R:" .
 
   88                        $insert[
"right"] . 
",sahs_id:" . $sahs_id . 
",user_id:" . $user_id . 
"\n");
 
   90                    $ilDB->insert(
'scorm_tracking', array(
 
   91                        'obj_id' => array(
'integer', $obj_id),
 
   92                        'user_id' => array(
'integer', $user_id),
 
   93                        'sco_id' => array(
'integer', $sahs_id),
 
   94                        'lvalue' => array(
'text', $insert[
"left"]),
 
   95                        'rvalue' => array(
'clob', $insert[
"right"]),
 
   99                    fwrite(
$f, 
"Insert - L:" . $insert[
"left"] . 
",R:" .
 
  100                        $insert[
"right"] . 
",sahs_id:" . $sahs_id . 
",user_id:" . $user_id . 
"\n");
 
  103            foreach ($this->update as $update) {
 
  104                $set = 
$ilDB->queryF(
 
  106                                SELECT * FROM scorm_tracking  
  111                    array(
'integer',
'integer',
'text',
'integer'),
 
  112                    array($user_id,$sahs_id,$update[
"left"],$obj_id)
 
  115                if ($rec = 
$ilDB->fetchAssoc($set)) {
 
  119                            'rvalue' => array(
'clob', $update[
"right"]),
 
  123                            'user_id' => array(
'integer', $user_id),
 
  124                            'sco_id' => array(
'integer', $sahs_id),
 
  125                            'lvalue' => array(
'text', $update[
"left"]),
 
  126                            'obj_id' => array(
'integer', $obj_id)
 
  130                    fwrite(
$f, 
"ERROR Update, left value does not exist. L:" . $update[
"left"] . 
",R:" .
 
  131                        $update[
"right"] . 
",sahs_id:" . $sahs_id . 
",user_id:" . $user_id . 
"\n");
 
  138        include_once(
"./Services/Tracking/classes/class.ilLPStatusWrapper.php");
 
  156        $obj_id = (int) 
$_GET[
"package_id"];
 
  157        $in = file_get_contents(
"php://input");
 
  160        $user_id = (int) 
$data->p;
 
  162        header(
'Content-Type: text/plain; charset=UTF-8');
 
  166            print(
"storeJsApiCmi failed");
 
  170                print(
"syncGlobalStatus failed");
 
  184        $b_updateStatus = 
false;
 
  188        $b_messageLog = 
false;
 
  189        if (
$ilLog->current_log_level == 30) {
 
  190            $b_messageLog = 
true;
 
  194            $ilLog->write(
"ScormAicc: CALLING SCORM storeJsApi() " . 
$_POST);
 
  205            $aa_data[] = array(
"sco_id" => (
int) 
$data->cmi[
$i][0], 
"left" => 
$data->cmi[
$i][1], 
"right" => 
$data->cmi[
$i][2]);
 
  210            $ilLog->write(
"ScormAicc: storeJsApi: Error: No valid obj_id given.");
 
  212            foreach ($aa_data as $a_data) {
 
  213                $set = 
$ilDB->queryF(
 
  215                                SELECT rvalue FROM scorm_tracking  
  220                    array(
'integer',
'integer',
'text',
'integer'),
 
  221                    array($user_id,$a_data[
"sco_id"],$a_data[
"left"],$obj_id)
 
  223                if ($rec = 
$ilDB->fetchAssoc($set)) {
 
  224                    if ($a_data[
"left"] == 
'cmi.core.lesson_status' && $a_data[
"right"] != $rec[
"rvalue"]) {
 
  225                        $b_updateStatus = 
true;
 
  230                            'rvalue' => array(
'clob', $a_data[
"right"]),
 
  234                            'user_id' => array(
'integer', $user_id),
 
  235                            'sco_id' => array(
'integer', $a_data[
"sco_id"]),
 
  236                            'lvalue' => array(
'text', $a_data[
"left"]),
 
  237                            'obj_id' => array(
'integer', $obj_id)
 
  241                        $ilLog->write(
"ScormAicc: storeJsApi Updated - L:" . $a_data[
"left"] . 
",R:" .
 
  242                        $a_data[
"right"] . 
" for obj_id:" . $obj_id . 
",sco_id:" . $a_data[
"sco_id"] . 
",user_id:" . $user_id);
 
  245                    if ($a_data[
"left"] == 
'cmi.core.lesson_status') {
 
  246                        $b_updateStatus = 
true;
 
  248                    $ilDB->insert(
'scorm_tracking', array(
 
  249                        'obj_id' => array(
'integer', $obj_id),
 
  250                        'user_id' => array(
'integer', $user_id),
 
  251                        'sco_id' => array(
'integer', $a_data[
"sco_id"]),
 
  252                        'lvalue' => array(
'text', $a_data[
"left"]),
 
  253                        'rvalue' => array(
'clob', $a_data[
"right"]),
 
  257                        $ilLog->write(
"ScormAicc: storeJsApi Inserted - L:" . $a_data[
"left"] . 
",R:" .
 
  258                        $a_data[
"right"] . 
" for obj_id:" . $obj_id . 
",sco_id:" . $a_data[
"sco_id"] . 
",user_id:" . $user_id);
 
  261                if ($a_data[
"left"] == 
'cmi.core.score.max') {
 
  262                    $i_score_max = $a_data[
"right"];
 
  264                if ($a_data[
"left"] == 
'cmi.core.score.raw') {
 
  265                    $i_score_raw = $a_data[
"right"];
 
  269            if ($i_score_max > 0 && $i_score_raw > 0) {
 
  272                        ($i_score_raw / $i_score_max) * 100);
 
  292        $saved_global_status = 
$data->saved_global_status;
 
  293        $ilLog->write(
"saved_global_status=" . $saved_global_status);
 
  296        if (!
$data->packageAttempts) {
 
  297            $val_set = 
$ilDB->queryF(
 
  298                'SELECT package_attempts FROM sahs_user WHERE obj_id = %s AND user_id = %s',
 
  299                array(
'integer',
'integer'),
 
  302            $val_rec = 
$ilDB->fetchAssoc($val_set);
 
  303            $attempts = $val_rec[
"package_attempts"];
 
  305            $attempts = 
$data->packageAttempts;
 
  307        if ($attempts == 
null) {
 
  312        $totalTime = (int) 
$data->totalTimeCentisec;
 
  313        $totalTime = round($totalTime / 100);
 
  315            'UPDATE sahs_user SET last_visited=%s, last_access = %s, sco_total_time_sec=%s, status=%s, percentage_completed=%s, package_attempts=%s WHERE obj_id = %s AND user_id = %s',
 
  316            array(
'text', 
'timestamp', 
'integer', 
'integer', 
'integer', 
'integer', 
'integer', 
'integer'),
 
  317            array(
$data->last_visited, date(
'Y-m-d H:i:s'), $totalTime, $new_global_status, 
$data->percentageCompleted, $attempts, 
$packageId, $userId)
 
  322        $ilObjDataCache = 
$DIC[
'ilObjDataCache'];
 
  323        include_once(
"./Services/Tracking/classes/class.ilChangeEvent.php");
 
  329        if ($new_global_status != 
null) {
 
  330            include_once(
"./Services/Tracking/classes/class.ilObjUserTracking.php");
 
  331            include_once(
"./Services/Tracking/classes/class.ilLPStatus.php");
 
  351        $val_set = 
$ilDB->queryF(
 
  352            'SELECT package_attempts, total_time_sec, sco_total_time_sec, time_from_lms FROM sahs_user, sahs_lm ' 
  353                                . 
'WHERE sahs_user.obj_id = %s AND sahs_user.user_id = %s AND sahs_user.obj_id = sahs_lm.id',
 
  354            array(
'integer',
'integer'),
 
  355            array($a_obj_id,$a_user_id)
 
  358        $val_rec = 
$ilDB->fetchAssoc($val_set);
 
  360        if ($val_rec[
"package_attempts"] == 
null) {
 
  361            $val_rec[
"package_attempts"] = 
"";
 
  363        $attempts = $val_rec[
"package_attempts"];
 
  369        $time = (int) $val_rec[
"sco_total_time_sec"];
 
  374            $sco_set = 
$ilDB->queryF(
 
  376                        SELECT sco_id, rvalue FROM scorm_tracking  
  381                array(
'integer',
'integer',
'text',
'integer'),
 
  382                array($a_obj_id,$a_user_id, 
'cmi.core.total_time',0)
 
  385            while ($sco_rec = 
$ilDB->fetchAssoc($sco_set)) {
 
  386                $tarr = explode(
":", $sco_rec[
"rvalue"]);
 
  387                $sec = (int) $tarr[2] + (
int) $tarr[1] * 60 +
 
  388                    (int) substr($tarr[0], strlen($tarr[0]) - 3) * 60 * 60;
 
  393        include_once(
"./Services/Tracking/classes/class.ilChangeEvent.php");
 
  403        $ilDB->insert(
'scorm_tracking', array(
 
  404            'obj_id' => array(
'integer', $a_obj_id),
 
  405            'user_id' => array(
'integer', 
$ilUser->getId()),
 
  406            'sco_id' => array(
'integer', $a_sahs_id),
 
  407            'lvalue' => array(
'text', $a_lval),
 
  408            'rvalue' => array(
'clob', $a_rval),
 
  412        if ($a_lval == 
"cmi.core.lesson_status") {
 
  413            include_once(
"./Services/Tracking/classes/class.ilLPStatusWrapper.php");
 
  425    public static function _getInProgress($scorm_item_id, $a_obj_id, $a_blocked_user_ids = 
null)
 
  430        if (is_array($scorm_item_id)) {
 
  431            $in = 
$ilDB->in(
'sco_id', $scorm_item_id, 
false, 
'integer');
 
  434                'SELECT user_id,sco_id FROM scorm_tracking 
  437                        GROUP BY user_id, sco_id',
 
  443                'SELECT user_id,sco_id FROM scorm_tracking                       
  446                array(
'integer',
'integer'),
 
  447                array($scorm_item_id,$a_obj_id)
 
  451        $in_progress = array();
 
  453        while ($row = 
$ilDB->fetchObject(
$res)) {
 
  455            if (!($a_blocked_user_ids &&
 
  456                is_array($a_blocked_user_ids[$row->sco_id]) &&
 
  457                in_array($row->user_id, $a_blocked_user_ids[$row->sco_id]))) {
 
  458                $in_progress[$row->sco_id][] = $row->user_id;
 
  475        if (is_array($scorm_item_id)) {
 
  476            $in = 
$ilDB->in(
'sco_id', $scorm_item_id, 
false, 
'integer');
 
  479                'SELECT DISTINCT(user_id) FROM scorm_tracking  
  483                        AND (' . 
$ilDB->like(
'rvalue', 
'clob', 
'completed') . 
' OR ' . 
$ilDB->like(
'rvalue', 
'clob', 
'passed') . 
')',
 
  484                array(
'integer',
'text'),
 
  485                array($a_obj_id,
'cmi.core.lesson_status')
 
  489                'SELECT DISTINCT(user_id) FROM scorm_tracking  
  493                        AND (' . 
$ilDB->like(
'rvalue', 
'clob', 
'completed') . 
' OR ' . 
$ilDB->like(
'rvalue', 
'clob', 
'passed') . 
')',
 
  494                array(
'integer',
'integer',
'text'),
 
  495                array($scorm_item_id,$a_obj_id,
'cmi.core.lesson_status')
 
  499        while ($row = 
$ilDB->fetchObject(
$res)) {
 
  500            $user_ids[] = $row->user_id;
 
  502        return $user_ids ? $user_ids : array();
 
  511        $status = 
"not_attempted";
 
  513        if (is_array($a_scos)) {
 
  514            $in = 
$ilDB->in(
'sco_id', $a_scos, 
false, 
'integer');
 
  517                'SELECT sco_id, rvalue FROM scorm_tracking  
  522                array(
'integer',
'text', 
'integer'),
 
  523                array($a_obj_id,
'cmi.core.lesson_status', $a_user_id)
 
  530                if ($rec[
"rvalue"] == 
"failed") {
 
  533                if ($rec[
"rvalue"] != 
"completed" && $rec[
"rvalue"] != 
"passed") {
 
  539                $status = 
"in_progress";
 
  541            if ($completed && $cnt == count($a_scos)) {
 
  542                $status = 
"completed";
 
  557        if (is_array($a_scos)) {
 
  558            $in = 
$ilDB->in(
'sco_id', $a_scos, 
false, 
'integer');
 
  561                'SELECT sco_id, rvalue FROM scorm_tracking  
  566                array(
'integer',
'text', 
'integer'),
 
  567                array($a_obj_id,
'cmi.core.lesson_status', $a_user_id)
 
  572                if ($rec[
"rvalue"] == 
"completed" || $rec[
"rvalue"] == 
"passed") {
 
  591        $query = 
'SELECT user_id, MAX(c_timestamp) tst ' .
 
  592            'FROM scorm_tracking ' .
 
  593            'WHERE obj_id = ' . 
$ilDB->quote($a_obj_id, 
'integer') . 
' ' .
 
  599            $users[$row->user_id] = $row->tst;
 
  617            'SELECT DISTINCT user_id FROM scorm_tracking  
  620            array(
'integer',
'text'),
 
  621            array($a_obj_id,
'cmi.core.lesson_status')
 
  626            $users[] = $row[
"user_id"];
 
  642        if (is_array($scorm_item_id)) {
 
  643            $in = 
$ilDB->in(
'sco_id', $scorm_item_id, 
false, 
'integer');
 
  647                                SELECT DISTINCT(user_id) FROM scorm_tracking  
  651                                AND ' . 
$ilDB->like(
'rvalue', 
'clob', 
'failed') . 
' ',
 
  652                array(
'integer',
'text'),
 
  653                array($a_obj_id,
'cmi.core.lesson_status')
 
  658                                SELECT DISTINCT(user_id) FROM scorm_tracking  
  662                                AND ' . 
$ilDB->like(
'rvalue', 
'clob', 
'failed') . 
' ',
 
  663                array(
'integer',
'integer',
'text'),
 
  664                array($scorm_item_id,$a_obj_id,
'cmi.core.lesson_status')
 
  668        while ($row = 
$ilDB->fetchObject(
$res)) {
 
  669            $user_ids[] = $row->user_id;
 
  671        return $user_ids ? $user_ids : array();
 
  685        $in = 
$ilDB->in(
'sco_id', $a_scorm_item_ids, 
false, 
'integer');
 
  691                        SELECT user_id, COUNT(user_id) completed FROM scorm_tracking 
  695                        AND (' . 
$ilDB->like(
'rvalue', 
'clob', 
'completed') . 
' OR ' . 
$ilDB->like(
'rvalue', 
'clob', 
'passed') . 
') 
  697            array(
'integer', 
'text'),
 
  698            array($a_obj_id, 
'cmi.core.lesson_status')
 
  700        while ($row = 
$ilDB->fetchObject(
$res)) {
 
  701            $users[$row->user_id] = $row->completed;
 
  703        return $users ? $users : array();
 
  717        $in = 
$ilDB->in(
'sco_id', $sco_item_ids, 
false, 
'integer');
 
  721                SELECT * FROM scorm_tracking  
  725            array(
'integer',
'text'),
 
  726            array($a_obj_id,
'cmi.core.lesson_status')
 
  729        $info[
'completed'] = array();
 
  730        $info[
'failed'] = array();
 
  733        while ($row = 
$ilDB->fetchObject(
$res)) {
 
  734            switch ($row->rvalue) {
 
  737                    $info[
'completed'][$row->sco_id][] = $row->user_id;
 
  738                    $user_ids[$row->sco_id][] = $row->user_id;
 
  742                    $info[
'failed'][$row->sco_id][] = $row->user_id;
 
  743                    $user_ids[$row->sco_id][] = $row->user_id;
 
  757        $user_id = (int) 
$_GET[
"p"];
 
  758        $ref_id = (int) 
$_GET[
"ref_id"];
 
  759        $obj_id = (int) 
$_GET[
"package_id"];
 
  761            $GLOBALS[
'DIC'][
'ilLog']->write(__METHOD__ . 
' no valid obj_id');
 
  763            $last_visited = (string) 
$_GET[
'last_visited'];
 
  764            $endDate = date(
'Y-m-d H:i:s', mktime(date(
'H'), date(
'i') + 5, date(
's'), date(
'm'), date(
'd'), date(
'Y')));
 
  767                                SET last_visited = %s, hash_end =%s, last_access = %s 
  768                                WHERE obj_id = %s AND user_id = %s',
 
  769                array(
'text', 
'timestamp', 
'timestamp', 
'integer', 
'integer'),
 
  770                array($last_visited, $endDate, date(
'Y-m-d H:i:s'), $obj_id, $user_id)
 
  776        header(
'Content-Type: text/plain; charset=UTF-8');
 
  785            'select hash from sahs_user where obj_id=%s AND user_id=%s AND hash_end>%s',
 
  786            array(
'integer',
'integer',
'timestamp'),
 
  790        if ($rowtmp[
'hash'] == $hash) {
 
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
if(php_sapi_name() !='cli') $in
An exception for terminatinating execution or to throw for unit testing.
static _recordReadEvent( $a_type, $a_ref_id, $obj_id, $usr_id, $isCatchupWriteEvents=true, $a_ext_rc=false, $a_ext_time=false)
Records a read event and catches up with write events.
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
static writeStatus($a_obj_id, $a_user_id, $a_status, $a_percentage=false, $a_force_per=false, &$a_old_status=self::LP_STATUS_NOT_ATTEMPTED_NUM)
Write status for user and object.
static handleOutcomeWithoutLP($a_obj_id, $a_usr_id, $a_percentage)
Class ilObjSCORMTracking.
static _getTrackedUsers($a_obj_id)
Get all tracked users.
static _getProgressInfo($sco_item_ids, $a_obj_id)
Get info about.
static storeJsApi($obj_id=0)
static syncGlobalStatus($userId, $packageId, $data, $new_global_status)
static _getCompleted($scorm_item_id, $a_obj_id)
like necessary because of Oracle
static _countCompleted($a_scos, $a_obj_id, $a_user_id)
static _getInProgress($scorm_item_id, $a_obj_id, $a_blocked_user_ids=null)
static _getCollectionStatus($a_scos, $a_obj_id, $a_user_id)
static _syncReadEvent($a_obj_id, $a_user_id, $a_type, $a_ref_id)
Synch read event table.
static _getFailed($scorm_item_id, $a_obj_id)
like necessary because of Oracle
static lookupLastAccessTimes($a_obj_id)
Lookup last acccess time for all users of a scorm module @global ilDB $ilDB.
static storeJsApiCmi($user_id, $obj_id, $data)
static _getCountCompletedPerUser($a_scorm_item_ids, $a_obj_id)
Get users who have status completed or passed.
static _insertTrackData($a_sahs_id, $a_lval, $a_rval, $a_obj_id)
static checkIfAllowed($packageId, $userId, $hash)
store($obj_id=0, $sahs_id=0, $extractData=1)
static scorm12PlayerUnload()
static _lookupObjId($a_id)
static _lookupPresentableItems($a_slm_id)
Count number of presentable SCOs/Assets of SCORM learning module.
static now()
Return current timestamp in Y-m-d H:i:s format.
foreach($_POST as $key=> $value) $res