1<?php
2
3/* Copyright (c) 1998-2011 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5include_once './Services/Tracking/classes/class.ilLPStatus.php';
6
7/**
8 * @author Stefan Meyer <meyer@leifos.com>
9 *
10 * @version $Id$
11 *
12 * @package ilias-tracking
13 *
14 */
15class ilLPStatusSCORM extends ilLPStatus
16{
17    public function __construct($a_obj_id)
18    {
19        global $DIC;
20
21        $ilDB = $DIC['ilDB'];
22
23        parent::__construct($a_obj_id);
24        $this->db = $ilDB;
25    }
26
27
28    public static function _getInProgress($a_obj_id)
29    {
30        $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id);
31        $users = array();
32        foreach ($status_info['in_progress'] as $in_progress) {
33            $users = array_merge($users, $in_progress);
34        }
35        $users = array_unique($users);
36        $users = array_diff($users, ilLPStatusWrapper::_getCompleted($a_obj_id));
37        $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id));
38
39        return $users;
40    }
41
42    public static function _getCompleted($a_obj_id)
43    {
44        global $DIC;
45
46        $ilDB = $DIC['ilDB'];
47
48        include_once './Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php';
49
50        $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id);
51
52        $items = $status_info['scos'];
53
54        $counter = 0;
55        $users = array();
56        foreach ($items as $sco_id) {
57            $tmp_users = $status_info['completed'][$sco_id];
58
59            if (!$counter++) {
60                $users = $tmp_users;
61            } else {
62                $users = array_intersect($users, $tmp_users);
63            }
64        }
65
66        $users = array_diff($users, ilLPStatusWrapper::_getFailed($a_obj_id));
67        return $users;
68    }
69
70    public static function _getFailed($a_obj_id)
71    {
72        $status_info = ilLPStatusWrapper::_getStatusInfo($a_obj_id);
73
74        if (!count($status_info['scos'])) {
75            return array();
76        }
77        $users = array();
78        foreach ($status_info['scos'] as $sco_id) {
79            /* #17913 - max attempts were removed in 5.1
80            // max attempts vs. failed
81            if(sizeof($status_info['in_progress'][$sco_id]))
82            {
83                foreach($status_info['in_progress'][$sco_id] as $user_id)
84                {
85                    if(!in_array($user_id, $status_info['failed'][$sco_id]))
86                    {
87                        switch($status_info["subtype"])
88                        {
89                            case 'hacp':
90                            case 'aicc':
91                            case 'scorm':
92                                include_once './Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php';
93                                $has_max_attempts = ilObjSCORMTracking::_hasMaxAttempts($a_obj_id, $user_id);
94                                break;
95
96                            case 'scorm2004':
97                                include_once("./Modules/Scorm2004/classes/class.ilSCORM2004Tracking.php");
98                                $has_max_attempts = ilSCORM2004Tracking::_hasMaxAttempts($a_obj_id, $user_id);
99                                break;
100                        }
101
102                        if($has_max_attempts)
103                        {
104                            $status_info['failed'][$sco_id][] = $user_id;
105                        }
106                    }
107                }
108            }
109            */
110
111            $users = array_merge($users, (array) $status_info['failed'][$sco_id]);
112        }
113        return array_unique($users);
114    }
115
116    public static function _getNotAttempted($a_obj_id)
117    {
118        $users = array();
119
120        $members = ilObjectLP::getInstance($a_obj_id)->getMembers();
121        if ($members) {
122            // diff in progress and completed (use stored result in LPStatusWrapper)
123            $users = array_diff((array) $members, ilLPStatusWrapper::_getInProgress($a_obj_id));
124            $users = array_diff((array) $users, ilLPStatusWrapper::_getCompleted($a_obj_id));
125            $users = array_diff((array) $users, ilLPStatusWrapper::_getFailed($a_obj_id));
126        }
127
128        return $users;
129    }
130
131
132    public static function _getStatusInfo($a_obj_id)
133    {
134        // Which sco's determine the status
135        include_once './Services/Object/classes/class.ilObjectLP.php';
136        $olp = ilObjectLP::getInstance($a_obj_id);
137        $collection = $olp->getCollectionInstance();
138        if ($collection) {
139            $status_info['scos'] = $collection->getItems();
140        } else {
141            $status_info['scos'] = array();
142        }
143        $status_info['num_scos'] = count($status_info['scos']);
144
145        // Get subtype
146        include_once './Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php';
147        $status_info['subtype'] = ilObjSAHSLearningModule::_lookupSubType($a_obj_id);
148
149        switch ($status_info['subtype']) {
150            case 'hacp':
151            case 'aicc':
152                include_once './Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php';
153                $status_info['num_completed'] = ilObjSCORMTracking::_getCountCompletedPerUser($status_info['scos'], $a_obj_id);
154
155                include_once './Modules/ScormAicc/classes/class.ilObjAICCLearningModule.php';
156                foreach (ilObjAICCLearningModule::_getTrackingItems($a_obj_id) as $item) {
157                    if (in_array($item['obj_id'], $status_info['scos'])) {
158                        $status_info['scos_title']["$item[obj_id]"] = $item['title'];
159                    }
160                }
161                $info = ilObjSCORMTracking::_getProgressInfo($status_info['scos'], $a_obj_id);
162                break;
163
164            case 'scorm':
165                include_once './Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php';
166                $status_info['num_completed'] = ilObjSCORMTracking::_getCountCompletedPerUser($status_info['scos'], $a_obj_id);
167
168                include_once './Modules/ScormAicc/classes/SCORM/class.ilSCORMItem.php';
169                foreach ($status_info['scos'] as $sco_id) {
170                    $status_info['scos_title'][$sco_id] = ilSCORMItem::_lookupTitle($sco_id);
171                }
172                $info = ilObjSCORMTracking::_getProgressInfo($status_info['scos'], $a_obj_id);
173                break;
174
175            case "scorm2004":
176                include_once './Modules/Scorm2004/classes/class.ilSCORM2004Tracking.php';
177                $status_info['num_completed'] = ilSCORM2004Tracking::_getCountCompletedPerUser($status_info['scos'], $a_obj_id, true);
178                include_once './Modules/Scorm2004/classes/class.ilObjSCORM2004LearningModule.php';
179                foreach ($status_info['scos'] as $sco_id) {
180                    $status_info['scos_title'][$sco_id] = ilObjSCORM2004LearningModule::_lookupItemTitle($sco_id);
181                }
182
183                $info = ilSCORM2004Tracking::_getItemProgressInfo($status_info['scos'], $a_obj_id, true);
184                break;
185        }
186
187        $status_info['completed'] = array();
188        $status_info['failed'] = array();
189        $status_info['in_progress'] = array();
190        foreach ($status_info['scos'] as $sco_id) {
191            $status_info['completed'][$sco_id] = $info['completed'][$sco_id] ? $info['completed'][$sco_id] : array();
192            $status_info['failed'][$sco_id] = $info['failed'][$sco_id] ? $info['failed'][$sco_id] : array();
193            $status_info['in_progress'][$sco_id] = $info['in_progress'][$sco_id] ? $info['in_progress'][$sco_id] : array();
194        }
195        //var_dump($status_info["completed"]);
196        return $status_info;
197    }
198
199    /**
200     * Determine status
201     *
202     * @param	integer		object id
203     * @param	integer		user id
204     * @param	object		object (optional depends on object type)
205     * @return	integer		status
206     */
207    public function determineStatus($a_obj_id, $a_user_id, $a_obj = null)
208    {
209        global $DIC;
210
211        $ilObjDataCache = $DIC['ilObjDataCache'];
212        $ilDB = $DIC['ilDB'];
213        $ilLog = $DIC['ilLog'];
214
215        $status = self::LP_STATUS_NOT_ATTEMPTED_NUM;
216
217        // if the user has accessed the scorm object
218        // the status is at least "in progress"
219        include_once("./Services/Tracking/classes/class.ilChangeEvent.php");
220        if (ilChangeEvent::hasAccessed($a_obj_id, $a_user_id)) {
221            $status = self::LP_STATUS_IN_PROGRESS_NUM;
222        }
223        //$ilLog->write("-".$status."-");
224
225        // Which sco's determine the status
226        include_once './Services/Object/classes/class.ilObjectLP.php';
227        $olp = ilObjectLP::getInstance($a_obj_id);
228        $collection = $olp->getCollectionInstance();
229        if ($collection) {
230            $scos = $collection->getItems();
231            if (sizeof($scos)) { // #15462 (#11513 - empty collections cannot be completed)
232                include_once './Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php';
233                $subtype = ilObjSAHSLearningModule::_lookupSubType($a_obj_id);
234                switch ($subtype) {
235                    case 'hacp':
236                    case 'aicc':
237                    case 'scorm':
238                        include_once("./Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php");
239                        $scorm_status = ilObjSCORMTracking::_getCollectionStatus($scos, $a_obj_id, $a_user_id);
240                        break;
241
242                    case 'scorm2004':
243                        include_once("./Modules/Scorm2004/classes/class.ilSCORM2004Tracking.php");
244                        $scorm_status = ilSCORM2004Tracking::_getCollectionStatus($scos, $a_obj_id, $a_user_id);
245                        break;
246                }
247
248                switch ($scorm_status) {
249                    case "in_progress":
250                        $status = self::LP_STATUS_IN_PROGRESS_NUM;
251                        break;
252                    case "completed":
253                        $status = self::LP_STATUS_COMPLETED_NUM;
254                        break;
255                    case "failed":
256                        $status = self::LP_STATUS_FAILED_NUM;
257                        break;
258                }
259            }
260        }
261
262        //$ilLog->write("-".$status."-");
263        return $status;
264    }
265
266    /**
267     * Determine percentage
268     *
269     * @param	integer		object id
270     * @param	integer		user id
271     * @param	object		object (optional depends on object type)
272     * @return	integer		percentage
273     */
274    public function determinePercentage($a_obj_id, $a_user_id, $a_obj = null)
275    {
276        // Which sco's determine the status
277        include_once './Services/Object/classes/class.ilObjectLP.php';
278        $olp = ilObjectLP::getInstance($a_obj_id);
279        $collection = $olp->getCollectionInstance();
280        if ($collection) {
281            $scos = $collection->getItems();
282            $reqscos = count($scos);
283
284            include_once './Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php';
285            $subtype = ilObjSAHSLearningModule::_lookupSubType($a_obj_id);
286            if ($subtype != "scorm2004") {
287                include_once("./Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php");
288                $compl = ilObjSCORMTracking::_countCompleted($scos, $a_obj_id, $a_user_id);
289            } else {
290                include_once("./Modules/Scorm2004/classes/class.ilSCORM2004Tracking.php");
291                $compl = ilSCORM2004Tracking::_countCompleted($scos, $a_obj_id, $a_user_id, true);
292            }
293        }
294
295        if ($reqscos > 0) {
296            $per = min(100, 100 / $reqscos * $compl);
297        } else {
298            $per = 100;
299        }
300
301        return $per;
302    }
303
304    public function refreshStatus($a_obj_id, $a_users = null)
305    {
306        parent::refreshStatus($a_obj_id, $a_users);
307
308        // this is restricted to SCOs in the current collection
309        include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
310        $in_progress = ilLPStatusWrapper::_getInProgress($a_obj_id);
311        $completed = ilLPStatusWrapper::_getCompleted($a_obj_id);
312        $failed = ilLPStatusWrapper::_getFailed($a_obj_id);
313        $all_active_users = array_unique(array_merge($in_progress, $completed, $failed));
314
315        // get all tracked users regardless of SCOs
316        include_once './Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php';
317        $subtype = ilObjSAHSLearningModule::_lookupSubType($a_obj_id);
318        if ($subtype != "scorm2004") {
319            include_once("./Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php");
320            $all_tracked_users = ilObjSCORMTracking::_getTrackedUsers($a_obj_id);
321        } else {
322            include_once("./Modules/Scorm2004/classes/class.ilSCORM2004Tracking.php");
323            $all_tracked_users = ilSCORM2004Tracking::_getTrackedUsers($a_obj_id);
324        }
325
326        $not_attempted_users = array_diff($all_tracked_users, $all_active_users);
327        unset($all_tracked_users);
328        unset($all_active_users);
329
330        // reset all users which have no data for the current SCOs
331        if ($not_attempted_users) {
332            foreach ($not_attempted_users as $usr_id) {
333                // this will update any (parent) collections if necessary
334                ilLPStatus::writeStatus($a_obj_id, $usr_id, self::LP_STATUS_NOT_ATTEMPTED_NUM, 0);
335            }
336        }
337    }
338}
339