ILIAS  release_8 Revision v8.24
class.ilSoapLearningProgressAdministration.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5include_once './webservice/soap/classes/class.ilSoapAdministration.php';
6
13{
15 protected static array $DELETE_PROGRESS_FILTER_TYPES = ['sahs', 'tst'];
16
17 public const PROGRESS_FILTER_ALL = 0;
19 public const PROGRESS_FILTER_COMPLETED = 2;
20 public const PROGRESS_FILTER_FAILED = 3;
22
27 public const SOAP_LP_ERROR_NO_PERMISSION = 58;
29
31 protected static array $PROGRESS_INFO_TYPES = [
37 ];
38
39 public const USER_FILTER_ALL = -1;
40
44 public function deleteProgress(string $sid, array $ref_ids, array $usr_ids, array $type_filter, array $progress_filter)
45 {
46 $this->initAuth($sid);
47 $this->initIlias();
48
49 if (!is_array($usr_ids)) {
50 $usr_ids = (array) $usr_ids;
51 }
52 if (!is_array($type_filter)) {
53 $type_filter = (array) $type_filter;
54 }
55
56 if (!$this->checkSession($sid)) {
57 return $this->raiseError($this->getMessage(), $this->getMessageCode());
58 }
59
60 if (array_diff($type_filter, self::$DELETE_PROGRESS_FILTER_TYPES)) {
61 return $this->raiseError('Invalid filter type given', 'Client');
62 }
63
64 include_once 'Services/User/classes/class.ilObjUser.php';
65 if (!in_array(self::USER_FILTER_ALL, $usr_ids) && !ilObjUser::userExists($usr_ids)) {
66 return $this->raiseError('Invalid user ids given', 'Client');
67 }
68
69 $valid_refs = array();
70 $type = '';
71 foreach ($ref_ids as $ref_id) {
74
75 // All containers
76 if ($GLOBALS['DIC']['objDefinition']->isContainer($type)) {
77 $all_sub_objs = array();
78 foreach (($type_filter) as $type_filter_item) {
79 $sub_objs = $GLOBALS['DIC']['tree']->getSubTree(
80 $GLOBALS['DIC']['tree']->getNodeData($ref_id),
81 false,
82 $type_filter_item
83 );
84 $all_sub_objs = array_merge($all_sub_objs, $sub_objs);
85 }
86
87 foreach ($all_sub_objs as $child_ref) {
88 $child_type = ilObject::_lookupType(ilObject::_lookupObjId($child_ref));
89 if (!$GLOBALS['DIC']['ilAccess']->checkAccess('write', '', $child_ref)) {
90 return $this->raiseError(
91 'Permission denied for : ' . $ref_id . ' -> type ' . $type,
92 'Client'
93 );
94 }
95 $valid_refs[] = $child_ref;
96 }
97 } elseif (in_array($type, $type_filter)) {
98 if (!$GLOBALS['DIC']['ilAccess']->checkAccess('write', '', $ref_id)) {
99 return $this->raiseError('Permission denied for : ' . $ref_id . ' -> type ' . $type, 'Client');
100 }
101 $valid_refs[] = $ref_id;
102 } else {
103 return $this->raiseError(
104 'Invalid object type given for : ' . $ref_id . ' -> type ' . $type,
105 'Client'
106 );
107 }
108 }
109
110 // Delete tracking data
111 foreach ($valid_refs as $ref_id) {
112 include_once './Services/Object/classes/class.ilObjectFactory.php';
114
115 if (!$obj instanceof ilObject) {
116 return $this->raiseError('Invalid reference id given : ' . $ref_id . ' -> type ' . $type, 'Client');
117 }
118
119 // filter users
120 $valid_users = $this->applyProgressFilter($obj->getId(), $usr_ids, $progress_filter);
121
122 switch ($obj->getType()) {
123 case 'sahs':
124 include_once './Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php';
125 $subtype = ilObjSAHSLearningModule::_lookupSubType($obj->getId());
126
127 switch ($subtype) {
128 case 'scorm':
129 $this->deleteScormTracking($obj->getId(), $valid_users);
130 break;
131
132 case 'scorm2004':
133 $this->deleteScorm2004Tracking($obj->getId(), $valid_users);
134 break;
135 }
136 break;
137
138 case 'tst':
139
141 $obj->removeTestResultsFromSoapLpAdministration(array_values($valid_users));
142 break;
143 }
144
145 // Refresh status
146 include_once './Services/Tracking/classes/class.ilLPStatusWrapper.php';
148 ilLPStatusWrapper::_refreshStatus($obj->getId(), $valid_users);
149 }
150 return true;
151 }
152
157 public function getProgressInfo(string $sid, int $a_ref_id, array $a_progress_filter)
158 {
159 global $DIC;
160
161 $this->initAuth($sid);
162 $this->initIlias();
163
164 $ilAccess = $DIC->access();
165
166 // Check session
167 if (!$this->checkSession($sid)) {
168 return $this->raiseError(
169 'Error ' . self::SOAP_LP_ERROR_AUTHENTICATION . ':' . $this->getMessage(),
170 self::SOAP_LP_ERROR_AUTHENTICATION
171 );
172 }
173
174 // Check filter
175 if (array_diff($a_progress_filter, self::$PROGRESS_INFO_TYPES)) {
176 return $this->raiseError(
177 'Error ' . self::SOAP_LP_ERROR_INVALID_FILTER . ': Invalid filter type given',
178 self::SOAP_LP_ERROR_INVALID_FILTER
179 );
180 }
181 // Check LP enabled
182 include_once("Services/Tracking/classes/class.ilObjUserTracking.php");
184 return $this->raiseError(
185 'Error ' . self::SOAP_LP_ERROR_LP_NOT_ENABLED . ': Learning progress not enabled in ILIAS',
186 self::SOAP_LP_ERROR_LP_NOT_ENABLED
187 );
188 }
189
190 include_once './Services/Object/classes/class.ilObjectFactory.php';
191 $obj = ilObjectFactory::getInstanceByRefId($a_ref_id, false);
192 if (!$obj instanceof ilObject) {
193 return $this->raiseError(
194 'Error ' . self::SOAP_LP_ERROR_INVALID_REF_ID . ': Invalid reference id ' . $a_ref_id . ' given',
195 self::SOAP_LP_ERROR_INVALID_REF_ID
196 );
197 }
198
199 // check lp available
200 include_once './Services/Tracking/classes/class.ilLPObjSettings.php';
201 $mode = ilLPObjSettings::_lookupDBMode($obj->getId());
203 return $this->raiseError(
204 'Error ' . self::SOAP_LP_ERROR_LP_NOT_AVAILABLE . ': Learning progress not available for objects of type ' .
205 $obj->getType(),
206 self::SOAP_LP_ERROR_LP_NOT_AVAILABLE
207 );
208 }
209
210 // check rbac
214 if (!$ilAccess->checkRbacOrPositionPermissionAccess(
215 'read_learning_progress',
216 'read_learning_progress',
217 $a_ref_id
218 )) {
219 return $this->raiseError(
220 'Error ' . self::SOAP_LP_ERROR_NO_PERMISSION . ': No Permission to access learning progress in this object',
221 self::SOAP_LP_ERROR_NO_PERMISSION
222 );
223 }
224
225 include_once './Services/Xml/classes/class.ilXmlWriter.php';
226 $writer = new ilXmlWriter();
227 $writer->xmlStartTag(
228 'LearningProgressInfo',
229 array(
230 'ref_id' => $obj->getRefId(),
231 'type' => $obj->getType()
232 )
233 );
234
235 $writer->xmlStartTag('LearningProgressSummary');
236
237 include_once './Services/Tracking/classes/class.ilLPStatusWrapper.php';
238 if (in_array(self::PROGRESS_FILTER_ALL, $a_progress_filter) || in_array(
239 self::PROGRESS_FILTER_COMPLETED,
240 $a_progress_filter
241 )) {
242 $completed = ilLPStatusWrapper::_getCompleted($obj->getId());
243 $completed = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
244 'read_learning_progress',
246 $a_ref_id,
247 $completed
248 );
249 $completed = count($completed);
250
251 $writer->xmlElement(
252 'Status',
253 array(
254 'type' => self::PROGRESS_FILTER_COMPLETED,
255 'num' => $completed
256 )
257 );
258 }
259 if (in_array(self::PROGRESS_FILTER_ALL, $a_progress_filter) || in_array(
260 self::PROGRESS_FILTER_IN_PROGRESS,
261 $a_progress_filter
262 )) {
263 $completed = ilLPStatusWrapper::_getInProgress($obj->getId());
264 $completed = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
265 'read_learning_progress',
267 $a_ref_id,
268 $completed
269 );
270 $completed = count($completed);
271
272 $writer->xmlElement(
273 'Status',
274 array(
275 'type' => self::PROGRESS_FILTER_IN_PROGRESS,
276 'num' => $completed
277 )
278 );
279 }
280 if (in_array(self::PROGRESS_FILTER_ALL, $a_progress_filter) || in_array(
281 self::PROGRESS_FILTER_FAILED,
282 $a_progress_filter
283 )) {
284 $completed = ilLPStatusWrapper::_getFailed($obj->getId());
285 $completed = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
286 'read_learning_progress',
288 $a_ref_id,
289 $completed
290 );
291 $completed = count($completed);
292
293 $writer->xmlElement(
294 'Status',
295 array(
296 'type' => self::PROGRESS_FILTER_FAILED,
297 'num' => $completed
298 )
299 );
300 }
301 if (in_array(self::PROGRESS_FILTER_ALL, $a_progress_filter) || in_array(
302 self::PROGRESS_FILTER_NOT_ATTEMPTED,
303 $a_progress_filter
304 )) {
305 $completed = ilLPStatusWrapper::_getNotAttempted($obj->getId());
306 $completed = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
307 'read_learning_progress',
309 $a_ref_id,
310 $completed
311 );
312 $completed = count($completed);
313
314 $writer->xmlElement(
315 'Status',
316 array(
317 'type' => self::PROGRESS_FILTER_NOT_ATTEMPTED,
318 'num' => $completed
319 )
320 );
321 }
322 $writer->xmlEndTag('LearningProgressSummary');
323 $writer->xmlStartTag('UserProgress');
324 if (in_array(self::PROGRESS_FILTER_ALL, $a_progress_filter) || in_array(
325 self::PROGRESS_FILTER_COMPLETED,
326 $a_progress_filter
327 )) {
328 $completed = ilLPStatusWrapper::_getCompleted($obj->getId());
329 $completed = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
330 'read_learning_progress',
332 $a_ref_id,
333 $completed
334 );
335
336 $this->addUserProgress($writer, $completed, self::PROGRESS_FILTER_COMPLETED);
337 }
338 if (in_array(self::PROGRESS_FILTER_ALL, $a_progress_filter) || in_array(
339 self::PROGRESS_FILTER_IN_PROGRESS,
340 $a_progress_filter
341 )) {
342 $completed = ilLPStatusWrapper::_getInProgress($obj->getId());
343 $completed = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
344 'read_learning_progress',
346 $a_ref_id,
347 $completed
348 );
349 $this->addUserProgress($writer, $completed, self::PROGRESS_FILTER_IN_PROGRESS);
350 }
351 if (in_array(self::PROGRESS_FILTER_ALL, $a_progress_filter) || in_array(
352 self::PROGRESS_FILTER_FAILED,
353 $a_progress_filter
354 )) {
355 $completed = ilLPStatusWrapper::_getFailed($obj->getId());
356 $completed = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
357 'read_learning_progress',
359 $a_ref_id,
360 $completed
361 );
362 $this->addUserProgress($writer, $completed, self::PROGRESS_FILTER_FAILED);
363 }
364 if (in_array(self::PROGRESS_FILTER_ALL, $a_progress_filter) || in_array(
365 self::PROGRESS_FILTER_NOT_ATTEMPTED,
366 $a_progress_filter
367 )) {
368 $completed = ilLPStatusWrapper::_getNotAttempted($obj->getId());
369 $completed = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
370 'read_learning_progress',
372 $a_ref_id,
373 $completed
374 );
375
376 $this->addUserProgress($writer, $completed, self::PROGRESS_FILTER_NOT_ATTEMPTED);
377 }
378 $writer->xmlEndTag('UserProgress');
379 $writer->xmlEndTag('LearningProgressInfo');
380
381 return $writer->xmlDumpMem();
382 }
383
384 protected function addUserProgress(ilXmlWriter $writer, array $users, int $a_type) : void
385 {
386 foreach ($users as $user_id) {
387 $writer->xmlStartTag(
388 'User',
389 array(
390 'id' => $user_id,
391 'status' => $a_type
392 )
393 );
394
395 $info = ilObjUser::_lookupName($user_id);
396 $writer->xmlElement('Login', array(), (string) $info['login']);
397 $writer->xmlElement('Firstname', array(), (string) $info['firstname']);
398 $writer->xmlElement('Lastname', array(), (string) $info['lastname']);
399 $writer->xmlEndTag('User');
400 }
401 }
402
410 protected function applyProgressFilter(int $obj_id, array $usr_ids, array $filter) : array
411 {
412 include_once './Services/Tracking/classes/class.ilLPStatusWrapper.php';
413
414 $all_users = array();
415 if (in_array(self::USER_FILTER_ALL, $usr_ids)) {
416 $all_users = array_unique(
417 array_merge(
421 )
422 );
423 } else {
424 $all_users = $usr_ids;
425 }
426
427 if (!$filter || in_array(self::PROGRESS_FILTER_ALL, $filter)) {
428 $GLOBALS['DIC']['log']->write(__METHOD__ . ': Deleting all progress data');
429 return $all_users;
430 }
431
432 $filter_users = array();
433 if (in_array(self::PROGRESS_FILTER_IN_PROGRESS, $filter)) {
434 $GLOBALS['DIC']['log']->write(__METHOD__ . ': Filtering in progress.');
435 $filter_users = array_merge($filter, ilLPStatusWrapper::_getInProgress($obj_id));
436 }
437 if (in_array(self::PROGRESS_FILTER_COMPLETED, $filter)) {
438 $GLOBALS['DIC']['log']->write(__METHOD__ . ': Filtering completed.');
439 $filter_users = array_merge($filter, ilLPStatusWrapper::_getCompleted($obj_id));
440 }
441 if (in_array(self::PROGRESS_FILTER_FAILED, $filter)) {
442 $GLOBALS['DIC']['log']->write(__METHOD__ . ': Filtering failed.');
443 $filter_users = array_merge($filter, ilLPStatusWrapper::_getFailed($obj_id));
444 }
445
446 // Build intersection
447 return array_intersect($all_users, $filter_users);
448 }
449
453 protected function deleteScormTracking(int $a_obj_id, array $a_usr_ids) : bool
454 {
455 global $DIC;
456
457 $ilDB = $DIC['ilDB'];
458
459 $query = 'DELETE FROM scorm_tracking ' .
460 'WHERE ' . $ilDB->in('user_id', $a_usr_ids, false, 'integer') . ' ' .
461 'AND obj_id = ' . $ilDB->quote($a_obj_id, 'integer') . ' ';
462 $res = $ilDB->manipulate($query);
463 return true;
464 }
465
469 protected function deleteScorm2004Tracking(int $a_obj_id, array $a_usr_ids) : void
470 {
471 global $DIC;
472
473 $ilDB = $DIC['ilDB'];
474
475 $query = 'SELECT cp_node_id FROM cp_node ' .
476 'WHERE nodename = ' . $ilDB->quote('item', 'text') . ' ' .
477 'AND cp_node.slm_id = ' . $ilDB->quote($a_obj_id, 'integer');
478 $res = $ilDB->query($query);
479
480 $scos = array();
481 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
482 $scos[] = $row->cp_node_id;
483 }
484
485 $query = 'DELETE FROM cmi_node ' .
486 'WHERE ' . $ilDB->in('user_id', $a_usr_ids, false, 'integer') . ' ' .
487 'AND ' . $ilDB->in('cp_node_id', $scos, false, 'integer');
488 $ilDB->manipulate($query);
489 }
490
495 public function getLearningProgressChanges(string $sid, string $timestamp, bool $include_ref_ids, array $type_filter)
496 {
497 $this->initAuth($sid);
498 $this->initIlias();
499
500 if (!$this->checkSession($sid)) {
501 return $this->raiseError($this->getMessage(), $this->getMessageCode());
502 }
503 global $DIC;
504
505 $rbacsystem = $DIC['rbacsystem'];
506 $tree = $DIC['tree'];
507 $ilLog = $DIC['ilLog'];
508
509 // check administrator
510 $types = "";
511 if (is_array($type_filter)) {
512 $types = implode(",", $type_filter);
513 }
514
515 // output lp changes as xml
516 try {
517 include_once './Services/Tracking/classes/class.ilLPXmlWriter.php';
518 $writer = new ilLPXmlWriter(true);
519 $writer->setTimestamp($timestamp);
520 $writer->setIncludeRefIds($include_ref_ids);
521 $writer->setTypeFilter($type_filter);
522 $writer->write();
523
524 return $writer->xmlDumpMem(true);
525 } catch (UnexpectedValueException $e) {
526 return $this->raiseError($e->getMessage(), 'Client');
527 }
528 }
529}
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
foreach($mandatory_scripts as $file) $timestamp
Definition: buildRTE.php:70
static _lookupDBMode(int $a_obj_id)
static _refreshStatus(int $a_obj_id, ?array $a_users=null)
static _getInProgress(int $a_obj_id)
Static function to read users who have the status 'in_progress'.
static _getFailed(int $a_obj_id)
Static function to read the users who have the status 'completed'.
static _resetInfoCaches($a_obj_id)
static _getNotAttempted(int $a_obj_id)
Static function to read the number of user who have the status 'not_attempted'.
static _getCompleted(int $a_obj_id)
Static function to read the users who have the status 'completed'.
XML writer learning progress.
static _lookupSubType(int $a_obj_id)
lookup subtype id (scorm, )
static _lookupName(int $a_user_id)
lookup user name
static userExists(array $a_usr_ids=array())
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _lookupType(int $id, bool $reference=false)
static _lookupObjId(int $ref_id)
soap server Base class for all SOAP registered methods.
raiseError(string $a_message, $a_code)
This class handles all DB changes necessary for fraunhofer.
addUserProgress(ilXmlWriter $writer, array $users, int $a_type)
applyProgressFilter(int $obj_id, array $usr_ids, array $filter)
Apply progress filter.
getLearningProgressChanges(string $sid, string $timestamp, bool $include_ref_ids, array $type_filter)
deleteScorm2004Tracking(int $a_obj_id, array $a_usr_ids)
Delete scorm 2004 tracking.
deleteScormTracking(int $a_obj_id, array $a_usr_ids)
Delete SCORM Tracking.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
xmlElement(string $tag, $attrs=null, $data=null, $encode=true, $escape=true)
Writes a basic element (no children, just textual content)
xmlEndTag(string $tag)
Writes an endtag.
xmlStartTag(string $tag, ?array $attrs=null, bool $empty=false, bool $encode=true, bool $escape=true)
Writes a starttag.
global $DIC
Definition: feed.php:28
$ref_id
Definition: ltiauth.php:67
$res
Definition: ltiservices.php:69
$query
$type