ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
class.ilTrQuery.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
12 class ilTrQuery
13 {
14  public static function getObjectsStatusForUser($a_user_id, array $obj_refs)
15  {
16  global $ilDB;
17 
18  if (sizeof($obj_refs)) {
19  $obj_ids = array_keys($obj_refs);
20  self::refreshObjectsStatus($obj_ids, array($a_user_id));
21 
22  include_once "Services/Object/classes/class.ilObjectLP.php";
23  include_once "Services/Tracking/classes/class.ilLPStatus.php";
24 
25  // prepare object view modes
26  include_once 'Modules/Course/classes/class.ilObjCourse.php';
27  $view_modes = array();
28  $query = "SELECT obj_id, view_mode FROM crs_settings" .
29  " WHERE " . $ilDB->in("obj_id", $obj_ids, false, "integer");
30  $set = $ilDB->query($query);
31  while ($rec = $ilDB->fetchAssoc($set)) {
32  $view_modes[(int) $rec["obj_id"]] = (int) $rec["view_mode"];
33  }
34 
35  $sessions = self::getSessionData($a_user_id, $obj_ids);
36 
37  $query = "SELECT object_data.obj_id, title, CASE WHEN status IS NULL THEN " . ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM . " ELSE status END AS status," .
38  " status_changed, percentage, read_count+childs_read_count AS read_count, spent_seconds+childs_spent_seconds AS spent_seconds," .
39  " u_mode, type, visits, mark, u_comment" .
40  " FROM object_data" .
41  " LEFT JOIN ut_lp_settings ON (ut_lp_settings.obj_id = object_data.obj_id)" .
42  " LEFT JOIN read_event ON (read_event.obj_id = object_data.obj_id AND read_event.usr_id = " . $ilDB->quote($a_user_id, "integer") . ")" .
43  " LEFT JOIN ut_lp_marks ON (ut_lp_marks.obj_id = object_data.obj_id AND ut_lp_marks.usr_id = " . $ilDB->quote($a_user_id, "integer") . ")" .
44  // " WHERE (u_mode IS NULL OR u_mode <> ".$ilDB->quote(ilLPObjSettings::LP_MODE_DEACTIVATED, "integer").")".
45  " WHERE " . $ilDB->in("object_data.obj_id", $obj_ids, false, "integer") .
46  " ORDER BY title";
47  $set = $ilDB->query($query);
48  $result = array();
49  while ($rec = $ilDB->fetchAssoc($set)) {
50  $rec["comment"] = $rec["u_comment"];
51  unset($rec["u_comment"]);
52 
53  $rec["ref_ids"] = $obj_refs[(int) $rec["obj_id"]];
54  $rec["status"] = (int) $rec["status"];
55  $rec["percentage"] = (int) $rec["percentage"];
56  $rec["read_count"] = (int) $rec["read_count"];
57  $rec["spent_seconds"] = (int) $rec["spent_seconds"];
58  $rec["u_mode"] = (int) $rec["u_mode"];
59 
60  if ($rec["type"] == "sess") {
61  $session = $sessions[$rec["obj_id"]];
62  $rec["title"] = $session["title"];
63  // $rec["status"] = (int)$session["status"];
64  }
65 
66  // lp mode might not match object/course view mode
67  if ($rec["type"] == "crs" && $view_modes[$rec["obj_id"]] == IL_CRS_VIEW_OBJECTIVE) {
68  $rec["u_mode"] = ilLPObjSettings::LP_MODE_OBJECTIVES;
69  } elseif (!$rec["u_mode"]) {
70  $olp = ilObjectLP::getInstance($rec["obj_id"]);
71  $rec["u_mode"] = $olp->getCurrentMode();
72  }
73 
74  // can be default mode
75  if (/*$rec["u_mode"] != ilLPObjSettings::LP_MODE_DEACTIVATE*/ true) {
76  $result[] = $rec;
77  }
78  }
79  return $result;
80  }
81  }
82 
83  public static function getObjectivesStatusForUser($a_user_id, $a_obj_id, array $a_objective_ids)
84  {
85  global $ilDB;
86 
87  include_once "Modules/Course/classes/Objectives/class.ilLOUserResults.php";
88  $lo_lp_status = ilLOUserResults::getObjectiveStatusForLP($a_user_id, $a_obj_id, $a_objective_ids);
89 
90  $query = "SELECT crs_id, crs_objectives.objective_id AS obj_id, title," . $ilDB->quote("lobj", "text") . " AS type" .
91  " FROM crs_objectives" .
92  " WHERE " . $ilDB->in("crs_objectives.objective_id", $a_objective_ids, false, "integer") .
93  " AND active = " . $ilDB->quote(1, "integer") .
94  " ORDER BY position";
95  $set = $ilDB->query($query);
96  $result = array();
97  while ($rec = $ilDB->fetchAssoc($set)) {
98  if (array_key_exists($rec["obj_id"], $lo_lp_status)) {
99  $rec["status"] = $lo_lp_status[$rec["obj_id"]];
100  } else {
102  }
103  $result[] = $rec;
104  }
105 
106  return $result;
107  }
108 
109  public static function getSCOsStatusForUser($a_user_id, $a_parent_obj_id, array $a_sco_ids)
110  {
111  self::refreshObjectsStatus(array($a_parent_obj_id), array($a_user_id));
112 
113  // import score from tracking data
114  $scores_raw = $scores = array();
115  include_once './Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php';
116  $subtype = ilObjSAHSLearningModule::_lookupSubType($a_parent_obj_id);
117  switch ($subtype) {
118  case 'hacp':
119  case 'aicc':
120  case 'scorm':
121  include_once './Modules/ScormAicc/classes/class.ilObjSCORMLearningModule.php';
122  $module = new ilObjSCORMLearningModule($a_parent_obj_id, false);
123  $scores_raw = $module->getTrackingDataAgg($a_user_id);
124  break;
125 
126  case 'scorm2004':
127  include_once './Modules/Scorm2004/classes/class.ilObjSCORM2004LearningModule.php';
128  $module = new ilObjSCORM2004LearningModule($a_parent_obj_id, false);
129  $scores_raw = $module->getTrackingDataAgg($a_user_id);
130  break;
131  }
132  if ($scores_raw) {
133  foreach ($scores_raw as $item) {
134  $scores[$item["sco_id"]] = $item["score"];
135  }
136  unset($module);
137  unset($scores_raw);
138  }
139 
140  include_once 'Services/Tracking/classes/class.ilLPStatusWrapper.php';
141  $status_info = ilLPStatusWrapper::_getStatusInfo($a_parent_obj_id);
142 
143  $items = array();
144  foreach ($a_sco_ids as $sco_id) {
145  // #9719 - can have in_progress AND failed/completed
146  if (in_array($a_user_id, $status_info["failed"][$sco_id])) {
148  } elseif (in_array($a_user_id, $status_info["completed"][$sco_id])) {
150  } elseif (in_array($a_user_id, $status_info["in_progress"][$sco_id])) {
152  } else {
154  }
155 
156  $items[$sco_id] = array(
157  "title" => $status_info["scos_title"][$sco_id],
158  "status" => $status,
159  "type" => "sahs",
160  "score" => (int) $scores[$sco_id]
161  );
162  }
163 
164  return $items;
165  }
166 
174  public static function getSubItemsStatusForUser($a_user_id, $a_parent_obj_id, array $a_item_ids)
175  {
176  self::refreshObjectsStatus(array($a_parent_obj_id), array($a_user_id));
177 
178  switch (ilObject::_lookupType($a_parent_obj_id)) {
179  case "lm":
180  case "mcst":
181  include_once './Services/Object/classes/class.ilObjectLP.php';
182  $olp = ilObjectLP::getInstance($a_parent_obj_id);
183  $collection = $olp->getCollectionInstance();
184  if ($collection) {
185  $ref_ids = ilObject::_getAllReferences($a_parent_obj_id);
186  $ref_id = end($ref_ids);
187  $item_data = $collection->getPossibleItems($ref_id);
188  }
189  break;
190 
191  default:
192  return array();
193  }
194 
195  include_once 'Services/Tracking/classes/class.ilLPStatusWrapper.php';
196  $status_info = ilLPStatusWrapper::_getStatusInfo($a_parent_obj_id);
197 
198  $items = array();
199  foreach ($a_item_ids as $item_id) {
200  if (!isset($item_data[$item_id])) {
201  continue;
202  }
203 
204  if (in_array($a_user_id, $status_info["completed"][$item_id])) {
206  } elseif (in_array($a_user_id, $status_info["in_progress"][$item_id])) {
208  } else {
210  }
211 
212  $items[$item_id] = array(
213  "title" => $item_data[$item_id]["title"],
214  "status" => $status,
215  "type" => self::getSubItemType($a_parent_obj_id)
216  );
217  }
218 
219  return $items;
220  }
221 
236  public static function getUserDataForObject(
237  $a_ref_id,
238  $a_order_field = "",
239  $a_order_dir = "",
240  $a_offset = 0,
241  $a_limit = 9999,
242  array $a_filters = null,
243  array $a_additional_fields = null,
244  $check_agreement = false,
245  $privacy_fields = null
246  ) {
247  global $ilDB;
248 
249  $fields = array("usr_data.usr_id", "login", "active");
250  $udf = self::buildColumns($fields, $a_additional_fields);
251 
252  $where = array();
253  $where[] = "usr_data.usr_id <> " . $ilDB->quote(ANONYMOUS_USER_ID, "integer");
254 
255  // users
256  $left = "";
257  $a_users = self::getParticipantsForObject($a_ref_id);
258 
259  $obj_id = ilObject::_lookupObjectId($a_ref_id);
260  self::refreshObjectsStatus(array($obj_id), $a_users);
261 
262  if (is_array($a_users)) {
263  $left = "LEFT";
264  $where[] = $ilDB->in("usr_data.usr_id", $a_users, false, "integer");
265  }
266 
267  $query = " FROM usr_data " . $left . " JOIN read_event ON (read_event.usr_id = usr_data.usr_id" .
268  " AND read_event.obj_id = " . $ilDB->quote($obj_id, "integer") . ")" .
269  " LEFT JOIN ut_lp_marks ON (ut_lp_marks.usr_id = usr_data.usr_id " .
270  " AND ut_lp_marks.obj_id = " . $ilDB->quote($obj_id, "integer") . ")" .
271  " LEFT JOIN usr_pref ON (usr_pref.usr_id = usr_data.usr_id AND keyword = " . $ilDB->quote("language", "text") . ")" .
272  self::buildFilters($where, $a_filters);
273 
274  $queries = array(array("fields"=>$fields, "query"=>$query));
275 
276  // #9598 - if language is not in fields alias is missing
277  if ($a_order_field == "language") {
278  $a_order_field = "usr_pref.value";
279  }
280 
281  // udf data is added later on, not in this query
282  $udf_order = null;
283  if (!$a_order_field) {
284  $a_order_field = "login";
285  } elseif (substr($a_order_field, 0, 4) == "udf_") {
286  $udf_order = $a_order_field;
287  $a_order_field = null;
288  }
289 
290  $result = self::executeQueries($queries, $a_order_field, $a_order_dir, $a_offset, $a_limit);
291 
292  self::getUDFAndHandlePrivacy($result, $udf, $check_agreement, $privacy_fields, $a_filters);
293 
294  // as we cannot do this in the query, sort by custom field here
295  // this will not work with pagination!
296  if ($udf_order) {
297  include_once "Services/Utilities/classes/class.ilStr.php";
299  $result["set"],
300  $udf_order,
301  $a_order_dir
302  );
303  }
304 
305  return $result;
306  }
307 
317  protected static function getUDFAndHandlePrivacy(
318  array &$a_result,
319  array $a_udf = null,
320  $a_check_agreement = null,
321  array $a_privacy_fields = null,
322  array $a_filters = null
323  ) {
324  global $ilDB;
325 
326  if (!$a_result["cnt"]) {
327  return;
328  }
329 
330  if (is_array($a_udf) && count($a_udf) > 0) {
331  $query = "SELECT usr_id, field_id, value FROM udf_text WHERE " . $ilDB->in("field_id", $a_udf, false, "integer");
332  $set = $ilDB->query($query);
333  $udf = array();
334  while ($row = $ilDB->fetchAssoc($set)) {
335  $udf[$row["usr_id"]]["udf_" . $row["field_id"]] = $row["value"];
336  }
337  }
338 
339  // (course/group) user agreement
340  if ($a_check_agreement) {
341  // admins/tutors (write-access) will never have agreement ?!
342  include_once "Services/Membership/classes/class.ilMemberAgreement.php";
343  $agreements = ilMemberAgreement::lookupAcceptedAgreements($a_check_agreement);
344 
345  // public information for users
346  $query = "SELECT usr_id FROM usr_pref WHERE keyword = " . $ilDB->quote("public_profile", "text") .
347  " AND value = " . $ilDB->quote("y", "text") . " OR value = " . $ilDB->quote("g", "text");
348  $set = $ilDB->query($query);
349  $all_public = array();
350  while ($row = $ilDB->fetchAssoc($set)) {
351  $all_public[] = $row["usr_id"];
352  }
353  $query = "SELECT usr_id,keyword FROM usr_pref WHERE " . $ilDB->like("keyword", "text", "public_%", false) .
354  " AND value = " . $ilDB->quote("y", "text") . " AND " . $ilDB->in("usr_id", $all_public, "", "integer");
355  $set = $ilDB->query($query);
356  $public = array();
357  while ($row = $ilDB->fetchAssoc($set)) {
358  $public[$row["usr_id"]][] = substr($row["keyword"], 7);
359  }
360  unset($all_public);
361  }
362 
363  foreach ($a_result["set"] as $idx => $row) {
364  // add udf data
365  if (isset($udf[$row["usr_id"]])) {
366  $a_result["set"][$idx] = $row = array_merge($row, $udf[$row["usr_id"]]);
367  }
368 
369  // remove all private data - if active agreement and agreement not given by user
370  if (sizeof($a_privacy_fields) && $a_check_agreement && !in_array($row["usr_id"], $agreements)) {
371  foreach ($a_privacy_fields as $field) {
372  // check against public profile
373  if (isset($row[$field]) && (!isset($public[$row["usr_id"]]) ||
374  !in_array($field, $public[$row["usr_id"]]))) {
375  // remove complete entry - offending field was filtered
376  if (isset($a_filters[$field])) {
377  // we cannot remove row because of pagination!
378  foreach (array_keys($row) as $col_id) {
379  $a_result["set"][$idx][$col_id] = null;
380  }
381  $a_result["set"][$idx]["privacy_conflict"] = true;
382  // unset($a_result["set"][$idx]);
383  break;
384  }
385  // remove offending field
386  else {
387  $a_result["set"][$idx][$field] = false;
388  }
389  }
390  }
391  }
392  }
393 
394  // $a_result["cnt"] = sizeof($a_result["set"]);
395  }
396 
412  public static function getObjectsDataForUser(
413  $a_user_id,
414  $a_parent_obj_id,
415  $a_parent_ref_id,
416  $a_order_field = "",
417  $a_order_dir = "",
418  $a_offset = 0,
419  $a_limit = 9999,
420  array $a_filters = null,
421  array $a_additional_fields = null,
422  $use_collection = true
423  ) {
424  global $ilDB;
425 
426  $fields = array("object_data.obj_id", "title", "type");
427  self::buildColumns($fields, $a_additional_fields);
428 
429  $objects = self::getObjectIds($a_parent_obj_id, $a_parent_ref_id, $use_collection, true, array($a_user_id));
430 
431  $query = " FROM object_data LEFT JOIN read_event ON (object_data.obj_id = read_event.obj_id AND" .
432  " read_event.usr_id = " . $ilDB->quote($a_user_id, "integer") . ")" .
433  " LEFT JOIN ut_lp_marks ON (ut_lp_marks.usr_id = " . $ilDB->quote($a_user_id, "integer") . " AND" .
434  " ut_lp_marks.obj_id = object_data.obj_id)" .
435  " WHERE " . $ilDB->in("object_data.obj_id", $objects["object_ids"], false, "integer") .
436  self::buildFilters(array(), $a_filters);
437 
438  $queries = array();
439  $queries[] = array("fields"=>$fields, "query"=>$query);
440 
441  if (!in_array($a_order_field, $fields)) {
442  $a_order_field = "title";
443  }
444 
445  $result = self::executeQueries($queries, $a_order_field, $a_order_dir, $a_offset, $a_limit);
446  if ($result["cnt"]) {
447  // session data
448  $sessions = self::getSessionData($a_user_id, $objects["object_ids"]);
449 
450  foreach ($result["set"] as $idx => $item) {
451  if ($item["type"] == "sess") {
452  $session = $sessions[$item["obj_id"]];
453  $result["set"][$idx]["title"] = $session["title"];
454  $result["set"][$idx]["sort_title"] = $session["e_start"];
455  // $result["set"][$idx]["status"] = (int)$session["status"];
456  }
457 
458  $result["set"][$idx]["ref_id"] = $objects["ref_ids"][$item["obj_id"]];
459  }
460 
461  // scos data (:TODO: will not be part of offset/limit)
462  if ($objects["scorm"]) {
463  include_once("./Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php");
464  $subtype = ilObjSAHSLearningModule::_lookupSubType($a_parent_obj_id);
465  if ($subtype == "scorm2004") {
466  include_once("./Modules/Scorm2004/classes/class.ilObjSCORM2004LearningModule.php");
467  $sobj = new ilObjSCORM2004LearningModule($a_parent_ref_id, true);
468  $scos_tracking = $sobj->getTrackingDataAgg($a_user_id, true);
469  } else {
470  include_once("./Modules/ScormAicc/classes/class.ilObjSCORMLearningModule.php");
471  $sobj = new ilObjSCORMLearningModule($a_parent_ref_id, true);
472  $scos_tracking = array();
473  foreach ($sobj->getTrackingDataAgg($a_user_id) as $item) {
474  // format: hhhh:mm:ss ?!
475  if ($item["time"]) {
476  $time = explode(":", $item["time"]);
477  $item["time"] = $time[0]*60*60+$time[1]*60+$time[2];
478  }
479  $scos_tracking[$item["sco_id"]] = array("session_time"=>$item["time"]);
480  }
481  }
482 
483  foreach ($objects["scorm"]["scos"] as $sco) {
484  $row = array("title" => $objects["scorm"]["scos_title"][$sco],
485  "type" => "sco");
486 
488  if (in_array($a_user_id, $objects["scorm"]["completed"][$sco])) {
490  } elseif (in_array($a_user_id, $objects["scorm"]["failed"][$sco])) {
492  } elseif (in_array($a_user_id, $objects["scorm"]["in_progress"][$sco])) {
494  }
495  $row["status"] = $status;
496 
497  // add available tracking data
498  if (isset($scos_tracking[$sco])) {
499  if (isset($scos_tracking[$sco]["last_access"])) {
500  $date = new ilDateTime($scos_tracking[$sco]["last_access"], IL_CAL_DATETIME);
501  $row["last_access"] = $date->get(IL_CAL_UNIX);
502  }
503  $row["spent_seconds"] = $scos_tracking[$sco]["session_time"];
504  }
505 
506  $result["set"][] = $row;
507  $result["cnt"]++;
508  }
509  }
510 
511  // #15379 - objectives data
512  if ($objects["objectives_parent_id"]) {
513  include_once "Modules/Course/classes/class.ilCourseObjective.php";
514  include_once "Modules/Course/classes/Objectives/class.ilLOUserResults.php";
515  $objtv_ids = ilCourseObjective::_getObjectiveIds($objects["objectives_parent_id"], true);
516  foreach (self::getObjectivesStatusForUser($a_user_id, $objects["objectives_parent_id"], $objtv_ids) as $item) {
517  $result["set"][] = $item;
518  $result["cnt"]++;
519  }
520  }
521 
522  // subitem data
523  if ($objects["subitems"]) {
524  $sub_type = self::getSubItemType($a_parent_obj_id);
525  foreach ($objects["subitems"]["items"] as $item_id) {
526  $row = array("title" => $objects["subitems"]["item_titles"][$item_id],
527  "type" => $sub_type);
528 
530  if (in_array($a_user_id, $objects["subitems"]["completed"][$item_id])) {
532  }
533  $row["status"] = $status;
534 
535  $result["set"][] = $row;
536  $result["cnt"]++;
537  }
538  }
539  }
540  return $result;
541  }
542 
548  public static function getSubItemType($a_parent_obj_id)
549  {
550  switch (ilObject::_lookupType($a_parent_obj_id)) {
551  case "lm":
552  return "st";
553 
554  case "mcst":
555  return "mob";
556  }
557  }
558 
566  protected static function getSessionData($a_user_id, array $obj_ids)
567  {
568  global $ilDB;
569 
570  $query = "SELECT obj_id, title, e_start, e_end, CASE WHEN participated = 1 THEN 2 WHEN registered = 1 THEN 1 ELSE NULL END AS status," .
571  " mark, e_comment" .
572  " FROM event" .
573  " JOIN event_appointment ON (event.obj_id = event_appointment.event_id)" .
574  " LEFT JOIN event_participants ON (event_participants.event_id = event.obj_id AND usr_id = " . $ilDB->quote($a_user_id, "integer") . ")" .
575  " WHERE " . $ilDB->in("obj_id", $obj_ids, false, "integer");
576  $set = $ilDB->query($query);
577  $sessions = array();
578  while ($rec = $ilDB->fetchAssoc($set)) {
579  $rec["comment"] = $rec["e_comment"];
580  unset($rec["e_comment"]);
581 
583  new ilDateTime($rec["e_start"], IL_CAL_DATETIME),
584  new ilDateTime($rec["e_end"], IL_CAL_DATETIME)
585  );
586 
587  if ($rec["title"]) {
588  $rec["title"] = $date . ': ' . $rec["title"];
589  } else {
590  $rec["title"] = $date;
591  }
592  $sessions[$rec["obj_id"]] = $rec;
593  }
594  return $sessions;
595  }
596 
613  public static function getObjectsSummaryForObject(
614  $a_parent_obj_id,
615  $a_parent_ref_id,
616  $a_order_field = "",
617  $a_order_dir = "",
618  $a_offset = 0,
619  $a_limit = 9999,
620  array $a_filters = null,
621  array $a_additional_fields = null,
622  $a_preselected_obj_ids = null
623  ) {
624  global $ilDB;
625 
626  $fields = array();
627  self::buildColumns($fields, $a_additional_fields, true);
628 
629  $objects = array();
630  if ($a_preselected_obj_ids === null) {
631  $objects = self::getObjectIds($a_parent_obj_id, $a_parent_ref_id, false, false);
632  } else {
633  foreach ($a_preselected_obj_ids as $obj_id => $ref_ids) {
634  $objects["object_ids"][] = $obj_id;
635  $objects["ref_ids"][$obj_id] = array_pop($ref_ids);
636  }
637  }
638 
639  $result = array();
640  if ($objects) {
641  // object data
642  $set = $ilDB->query("SELECT obj_id,title,type FROM object_data" .
643  " WHERE " . $ilDB->in("obj_id", $objects["object_ids"], false, "integer"));
644  while ($rec = $ilDB->fetchAssoc($set)) {
645  $object_data[$rec["obj_id"]] = $rec;
646  if ($a_preselected_obj_ids) {
647  $object_data[$rec["obj_id"]]["ref_ids"] = $a_preselected_obj_ids[$rec["obj_id"]];
648  } else {
649  $object_data[$rec["obj_id"]]["ref_ids"] = array($objects["ref_ids"][$rec["obj_id"]]);
650  }
651  }
652 
653  foreach ($objects["ref_ids"] as $object_id => $ref_id) {
654  $object_result = self::getSummaryDataForObject($ref_id, $fields, $a_filters);
655  if (sizeof($object_result)) {
656  if ($object_data[$object_id]) {
657  $result[] = array_merge($object_data[$object_id], $object_result);
658  }
659  }
660  }
661 
662  // :TODO: objectives
663  if ($objects["objectives_parent_id"]) {
664  }
665  }
666 
667  return array("cnt"=>sizeof($result), "set"=>$result);
668  }
669 
678  protected static function getSummaryDataForObject($a_ref_id, array $fields, array $a_filters = null)
679  {
680  global $ilDB;
681 
682  $where = array();
683  $where[] = "usr_data.usr_id <> " . $ilDB->quote(ANONYMOUS_USER_ID, "integer");
684 
685  // users
686  $a_users = self::getParticipantsForObject($a_ref_id);
687 
688  $left = "";
689  if (is_array($a_users)) { // #14840
690  $left = "LEFT";
691  $where[] = $ilDB->in("usr_data.usr_id", $a_users, false, "integer");
692  }
693 
694  $obj_id = ilObject::_lookupObjectId($a_ref_id);
695  self::refreshObjectsStatus(array($obj_id), $a_users);
696 
697  $query = " FROM usr_data " . $left . " JOIN read_event ON (read_event.usr_id = usr_data.usr_id" .
698  " AND obj_id = " . $ilDB->quote($obj_id, "integer") . ")" .
699  " LEFT JOIN ut_lp_marks ON (ut_lp_marks.usr_id = usr_data.usr_id " .
700  " AND ut_lp_marks.obj_id = " . $ilDB->quote($obj_id, "integer") . ")" .
701  " LEFT JOIN usr_pref ON (usr_pref.usr_id = usr_data.usr_id AND keyword = " . $ilDB->quote("language", "text") . ")" .
702  self::buildFilters($where, $a_filters, true);
703 
704  $fields[] = 'COUNT(usr_data.usr_id) AS user_count';
705 
706  $queries = array();
707  $queries[] = array("fields"=>$fields, "query"=>$query, "count"=>"*");
708 
709  $result = self::executeQueries($queries);
710  $result = $result["set"][0];
711  $users_no = $result["user_count"];
712 
713  $valid = true;
714  if (!$users_no) {
715  $valid = false;
716  } elseif (isset($a_filters["user_total"])) {
717  if ($a_filters["user_total"]["from"] && $users_no < $a_filters["user_total"]["from"]) {
718  $valid = false;
719  } elseif ($a_filters["user_total"]["to"] && $users_no > $a_filters["user_total"]["to"]) {
720  $valid = false;
721  }
722  }
723 
724  if ($valid) {
725  $result["country"] = self::getSummaryPercentages("country", $query);
726  $result["sel_country"] = self::getSummaryPercentages("sel_country", $query);
727  $result["city"] = self::getSummaryPercentages("city", $query);
728  $result["gender"] = self::getSummaryPercentages("gender", $query);
729  $result["language"] = self::getSummaryPercentages("usr_pref.value", $query, "language");
730  $result["status"] = self::getSummaryPercentages("status", $query);
731  $result["mark"] = self::getSummaryPercentages("mark", $query);
732  } else {
733  $result = array();
734  }
735 
736  if ($result) {
737  $result["user_total"] = $users_no;
738  }
739 
740  return $result;
741  }
742 
751  protected static function getSummaryPercentages($field, $base_query, $alias = null)
752  {
753  global $ilDB;
754 
755  if (!$alias) {
756  $field_alias = $field;
757  } else {
758  $field_alias = $alias;
759  $alias = " AS " . $alias;
760  }
761 
762  // move having BEHIND group by
763  $having = "";
764  if (preg_match("/" . preg_quote(" [[--HAVING") . "(.+)" . preg_quote("HAVING--]]") . "/", $base_query, $hits)) {
765  $having = " HAVING " . $hits[1];
766  $base_query = str_replace($hits[0], "", $base_query);
767  }
768 
769  $query = "SELECT COUNT(*) AS counter, " . $field . $alias . " " . $base_query . " GROUP BY " . $field . $having . " ORDER BY counter DESC";
770  $set = $ilDB->query($query);
771  $result = array();
772  while ($rec = $ilDB->fetchAssoc($set)) {
773  $result[$rec[$field_alias]] = (int) $rec["counter"];
774  }
775  return $result;
776  }
777 
784  public static function getParticipantsForObject($a_ref_id)
785  {
786  global $tree;
787 
788  $obj_id = ilObject::_lookupObjectId($a_ref_id);
789  $obj_type = ilObject::_lookupType($obj_id);
790 
791  $members = [];
792 
793  // try to get participants from (parent) course/group
794  $members_read = false;
795  switch ($obj_type) {
796  case 'crs':
797  case 'grp':
798  $members_read = true;
799  $member_obj = ilParticipants::getInstance($a_ref_id);
800  $members = $member_obj->getMembers();
801  break;
802 
803 
804  /* Mantis 19296: Individual Assessment can be subtype of crs.
805  * But for LP view only his own members should be displayed.
806  * We need to return the members without checking the parent path. */
807  case "iass":
808  $members_read = true;
809  include_once("Modules/IndividualAssessment/classes/class.ilObjIndividualAssessment.php");
810  $iass = new ilObjIndividualAssessment($obj_id, false);
811  $members = $iass->loadMembers()->membersIds();
812  break;
813 
814  default:
815  // walk path to find course or group object and use members of that object
816  $path = $tree->getPathId($a_ref_id);
817  array_pop($path);
818  foreach (array_reverse($path) as $path_ref_id) {
819  $type = ilObject::_lookupType($path_ref_id, true);
820  if ($type == "crs" || $type == "grp") {
821  $members_read = true;
822  $members = self::getParticipantsForObject($path_ref_id);
823  }
824  }
825  break;
826  }
827 
828  // begin-patch ouf
829  if ($members_read) {
830  return $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
831  'read_learning_progress',
832  'read_learning_progress',
833  $a_ref_id,
834  $members
835  );
836  }
837 
838  $a_users = null;
839 
840  // no participants possible: use tracking/object data where possible
841  switch ($obj_type) {
842  case "sahs":
843  include_once("./Modules/ScormAicc/classes/class.ilObjSAHSLearningModule.php");
844  $subtype = ilObjSAHSLearningModule::_lookupSubType($obj_id);
845  if ($subtype == "scorm2004") {
846  // based on cmi_node/cp_node, used for scorm tracking data views
847  include_once("./Modules/Scorm2004/classes/class.ilObjSCORM2004LearningModule.php");
848  $mod = new ilObjSCORM2004LearningModule($obj_id, false);
849  $all = $mod->getTrackedUsers("");
850  if ($all) {
851  $a_users = array();
852  foreach ($all as $item) {
853  $a_users[] = $item["user_id"];
854  }
855  }
856  } else {
857  include_once("./Modules/ScormAicc/classes/SCORM/class.ilObjSCORMTracking.php");
858  $a_users = ilObjSCORMTracking::_getTrackedUsers($obj_id);
859  }
860  break;
861 
862  case "exc":
863  include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
864  include_once("./Modules/Exercise/classes/class.ilObjExercise.php");
865  $exc = new ilObjExercise($obj_id, false);
866  $members = new ilExerciseMembers($exc);
867  $a_users = $members->getMembers();
868  break;
869 
870  case "tst":
871  include_once "Services/Tracking/classes/class.ilLPStatusFactory.php";
873  $a_users = $class::getParticipants($obj_id);
874  break;
875 
876  case "svy":
877  include_once "Services/Tracking/classes/class.ilLPStatusFactory.php";
879  $a_users = $class::getParticipants($obj_id);
880  break;
881 
882  case "prg":
883  include_once("Modules/StudyProgramme/classes/class.ilObjStudyProgramme.php");
884  $prg = new ilObjStudyProgramme($obj_id, false);
885  $a_users = $prg->getIdsOfUsersWithRelevantProgress();
886  break;
887  default:
888  // keep null
889  break;
890  }
891 
892  if (is_null($a_users)) {
893  return $a_users;
894  }
895 
896  // begin-patch ouf
897  return $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
898  'read_learning_progress',
899  'read_learning_progress',
900  $a_ref_id,
901  $a_users
902  );
903  }
904 
913  protected static function buildFilters(array $where, array $a_filters = null, $a_aggregate = false)
914  {
915  global $ilDB;
916 
917  $having = array();
918 
919  if (is_array($a_filters) && sizeof($a_filters) > 0) {
920  foreach ($a_filters as $id => $value) {
921  switch ($id) {
922  case "login":
923  case "firstname":
924  case "lastname":
925  case "institution":
926  case "department":
927  case "street":
928  case "email":
929  case "matriculation":
930  case "country":
931  case "city":
932  case "title":
933  $where[] = $ilDB->like("usr_data." . $id, "text", "%" . $value . "%");
934  break;
935 
936  case "gender":
937  case "zipcode":
938  case "sel_country":
939  $where[] = "usr_data." . $id . " = " . $ilDB->quote($value, "text");
940  break;
941 
942  case "u_comment":
943  $where[] = $ilDB->like("ut_lp_marks." . $id, "text", "%" . $value . "%");
944  break;
945 
946  case "status":
948  // #10645 - not_attempted is default
949  $where[] = "(ut_lp_marks.status = " . $ilDB->quote(ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM, "text") .
950  " OR ut_lp_marks.status IS NULL)";
951  break;
952  }
953  // fallthrough
954 
955  // no break
956  case "mark":
957  $where[] = "ut_lp_marks." . $id . " = " . $ilDB->quote($value, "text");
958  break;
959 
960  case "percentage":
961  if (!$a_aggregate) {
962  if ($value["from"]) {
963  $where[] = "ut_lp_marks." . $id . " >= " . $ilDB->quote($value["from"], "integer");
964  }
965  if ($value["to"]) {
966  $where[] = "(ut_lp_marks." . $id . " <= " . $ilDB->quote($value["to"], "integer") .
967  " OR ut_lp_marks." . $id . " IS NULL)";
968  }
969  } else {
970  if ($value["from"]) {
971  $having[] = "ROUND(AVG(ut_lp_marks." . $id . ")) >= " . $ilDB->quote($value["from"], "integer");
972  }
973  if ($value["to"]) {
974  $having[] = "ROUND(AVG(ut_lp_marks." . $id . ")) <= " . $ilDB->quote($value["to"], "integer");
975  }
976  }
977  break;
978 
979  case "language":
980  $where[] = "usr_pref.value = " . $ilDB->quote($value, "text");
981  break;
982 
983  // timestamp
984  case "last_access":
985  if ($value["from"]) {
986  $value["from"] = substr($value["from"], 0, -2) . "00";
987  $value["from"] = new ilDateTime($value["from"], IL_CAL_DATETIME);
988  $value["from"] = $value["from"]->get(IL_CAL_UNIX);
989  }
990  if ($value["to"]) {
991  if (strlen($value["to"]) == 19) {
992  $value["to"] = substr($value["to"], 0, -2) . "59"; // #14858
993  }
994  $value["to"] = new ilDateTime($value["to"], IL_CAL_DATETIME);
995  $value["to"] = $value["to"]->get(IL_CAL_UNIX);
996  }
997  // fallthrough
998 
999  // no break
1000  case 'status_changed':
1001  // fallthrough
1002 
1003  case "registration":
1004  if ($id == "registration") {
1005  $id = "create_date";
1006  }
1007  // fallthrough
1008 
1009  // no break
1010  case "create_date":
1011  case "first_access":
1012  case "birthday":
1013  if ($value["from"]) {
1014  $where[] = $id . " >= " . $ilDB->quote($value["from"], "date");
1015  }
1016  if ($value["to"]) {
1017  if (strlen($value["to"]) == 19) {
1018  $value["to"] = substr($value["to"], 0, -2) . "59"; // #14858
1019  }
1020  $where[] = $id . " <= " . $ilDB->quote($value["to"], "date");
1021  }
1022  break;
1023 
1024  case "read_count":
1025  if (!$a_aggregate) {
1026  if ($value["from"]) {
1027  $where[] = "(read_event." . $id . "+read_event.childs_" . $id . ") >= " . $ilDB->quote($value["from"], "integer");
1028  }
1029  if ($value["to"]) {
1030  $where[] = "((read_event." . $id . "+read_event.childs_" . $id . ") <= " . $ilDB->quote($value["to"], "integer") .
1031  " OR (read_event." . $id . "+read_event.childs_" . $id . ") IS NULL)";
1032  }
1033  } else {
1034  if ($value["from"]) {
1035  $having[] = "SUM(read_event." . $id . "+read_event.childs_" . $id . ") >= " . $ilDB->quote($value["from"], "integer");
1036  }
1037  if ($value["to"]) {
1038  $having[] = "SUM(read_event." . $id . "+read_event.childs_" . $id . ") <= " . $ilDB->quote($value["to"], "integer");
1039  }
1040  }
1041  break;
1042 
1043  case "spent_seconds":
1044  if (!$a_aggregate) {
1045  if ($value["from"]) {
1046  $where[] = "(read_event." . $id . "+read_event.childs_" . $id . ") >= " . $ilDB->quote($value["from"], "integer");
1047  }
1048  if ($value["to"]) {
1049  $where[] = "((read_event." . $id . "+read_event.childs_" . $id . ") <= " . $ilDB->quote($value["to"], "integer") .
1050  " OR (read_event." . $id . "+read_event.childs_" . $id . ") IS NULL)";
1051  }
1052  } else {
1053  if ($value["from"]) {
1054  $having[] = "ROUND(AVG(read_event." . $id . "+read_event.childs_" . $id . ")) >= " . $ilDB->quote($value["from"], "integer");
1055  }
1056  if ($value["to"]) {
1057  $having[] = "ROUND(AVG(read_event." . $id . "+read_event.childs_" . $id . ")) <= " . $ilDB->quote($value["to"], "integer");
1058  }
1059  }
1060  break;
1061 
1062  default:
1063  // var_dump("unknown: ".$id);
1064  break;
1065  }
1066  }
1067  }
1068 
1069  $sql = "";
1070  if (sizeof($where)) {
1071  $sql .= " WHERE " . implode(" AND ", $where);
1072  }
1073  if (sizeof($having)) {
1074  // ugly "having" hack because of summary view
1075  $sql .= " [[--HAVING " . implode(" AND ", $having) . "HAVING--]]";
1076  }
1077 
1078  return $sql;
1079  }
1080 
1089  protected static function buildColumns(array &$a_fields, array $a_additional_fields = null, $a_aggregate = false)
1090  {
1091  if (sizeof($a_additional_fields)) {
1092  $udf = null;
1093  foreach ($a_additional_fields as $field) {
1094  if (substr($field, 0, 4) != "udf_") {
1095  $function = null;
1096  if ($a_aggregate) {
1097  $pos = strrpos($field, "_");
1098  if ($pos === false) {
1099  continue;
1100  }
1101  $function = strtoupper(substr($field, $pos+1));
1102  $field = substr($field, 0, $pos);
1103  if (!in_array($function, array("MIN", "MAX", "SUM", "AVG", "COUNT"))) {
1104  continue;
1105  }
1106  }
1107 
1108  switch ($field) {
1109  case 'org_units':
1110  break;
1111 
1112  case "language":
1113  if ($function) {
1114  $a_fields[] = $function . "(value) " . $field . "_" . strtolower($function);
1115  } else {
1116  $a_fields[] = "value as " . $field;
1117  }
1118  break;
1119 
1120  case "read_count":
1121  case "spent_seconds":
1122  if (!$function) {
1123  $a_fields[] = "(" . $field . "+childs_" . $field . ") " . $field;
1124  } else {
1125  if ($function == "AVG") {
1126  $a_fields[] = "ROUND(AVG(" . $field . "+childs_" . $field . "), 2) " . $field . "_" . strtolower($function);
1127  } else {
1128  $a_fields[] = $function . "(COALESCE(" . $field . ", 0) + COALESCE(childs_" . $field . ", 0)) " . $field . "_" . strtolower($function);
1129  }
1130  }
1131  break;
1132 
1133  case "read_count_spent_seconds":
1134  if ($function == "AVG") {
1135  $a_fields[] = "ROUND(AVG((spent_seconds+childs_spent_seconds)/(read_count+childs_read_count)), 2) " . $field . "_" . strtolower($function);
1136  }
1137  break;
1138 
1139  default:
1140  if ($function) {
1141  if ($function == "AVG") {
1142  $a_fields[] = "ROUND(AVG(" . $field . "), 2) " . $field . "_" . strtolower($function);
1143  } else {
1144  $a_fields[] = $function . "(" . $field . ") " . $field . "_" . strtolower($function);
1145  }
1146  } else {
1147  $a_fields[] = $field;
1148  }
1149  break;
1150  }
1151  } else {
1152  $udf[] = substr($field, 4);
1153  }
1154  }
1155 
1156  // clean-up
1157  $a_fields = array_unique($a_fields);
1158  if (is_array($udf)) {
1159  $udf = array_unique($udf);
1160  }
1161 
1162  return $udf;
1163  }
1164  }
1165 
1176  public static function getObjectIds($a_parent_obj_id, $a_parent_ref_id = false, $use_collection = true, $a_refresh_status = true, $a_user_ids = null)
1177  {
1178  include_once "Services/Object/classes/class.ilObjectLP.php";
1179 
1180  $object_ids = array($a_parent_obj_id);
1181  $ref_ids = array($a_parent_obj_id => $a_parent_ref_id);
1182  $objectives_parent_id = $scorm = $subitems = false;
1183 
1184  $olp = ilObjectLP::getInstance($a_parent_obj_id);
1185  $mode = $olp->getCurrentMode();
1186  switch ($mode) {
1187  // what about LP_MODE_SCORM_PACKAGE ?
1189  include_once "Services/Tracking/classes/class.ilLPStatusFactory.php";
1190  $status_scorm = get_class(ilLPStatusFactory::_getInstance($a_parent_obj_id, ilLPObjSettings::LP_MODE_SCORM));
1191  $scorm = $status_scorm::_getStatusInfo($a_parent_obj_id);
1192  break;
1193 
1195  if (ilObject::_lookupType($a_parent_obj_id) == "crs") {
1196  $objectives_parent_id = $a_parent_obj_id;
1197  }
1198  break;
1199 
1203  include_once "Services/Tracking/classes/class.ilLPStatusFactory.php";
1204  $status_coll_tlt = get_class(ilLPStatusFactory::_getInstance($a_parent_obj_id, $mode));
1205  $subitems = $status_coll_tlt::_getStatusInfo($a_parent_obj_id);
1206  break;
1207 
1208  default:
1209  // lp collection
1210  if ($use_collection) {
1211  $collection = $olp->getCollectionInstance();
1212  if ($collection) {
1213  foreach ($collection->getItems() as $child_ref_id) {
1214  $child_id = ilObject::_lookupObjId($child_ref_id);
1215  $object_ids[] = $child_id;
1216  $ref_ids[$child_id] = $child_ref_id;
1217  }
1218  }
1219  }
1220  // all objects in branch
1221  else {
1222  self::getSubTree($a_parent_ref_id, $object_ids, $ref_ids);
1223  $object_ids = array_unique($object_ids);
1224  }
1225 
1226  foreach ($object_ids as $idx => $object_id) {
1227  if (!$object_id) {
1228  unset($object_ids[$idx]);
1229  }
1230  }
1231  break;
1232  }
1233 
1234  if ($a_refresh_status) {
1235  self::refreshObjectsStatus($object_ids, $a_user_ids);
1236  }
1237 
1238  return array("object_ids" => $object_ids,
1239  "ref_ids" => $ref_ids,
1240  "objectives_parent_id" => $objectives_parent_id,
1241  "scorm" => $scorm,
1242  "subitems" => $subitems);
1243  }
1244 
1252  protected static function getSubTree($a_parent_ref_id, array &$a_object_ids, array &$a_ref_ids)
1253  {
1254  global $tree;
1255 
1256  $children = $tree->getChilds($a_parent_ref_id);
1257  if ($children) {
1258  foreach ($children as $child) {
1259  if ($child["type"] == "adm" || $child["type"] == "rolf") {
1260  continue;
1261  }
1262 
1263  // as there can be deactivated items in the collection
1264  // we should allow them here too
1265 
1266  $olp = ilObjectLP::getInstance($child["obj_id"]);
1267  $cmode = $olp->getCurrentMode();
1268 
1269  /* see ilPluginLP
1270  if($cmode == ilLPObjSettings::LP_MODE_PLUGIN)
1271  {
1272  // #11368
1273  include_once "Services/Repository/classes/class.ilRepositoryObjectPluginSlot.php";
1274  if(ilRepositoryObjectPluginSlot::isTypePluginWithLP($child["type"], false))
1275  {
1276  $a_object_ids[] = $child["obj_id"];
1277  $a_ref_ids[$child["obj_id"]] = $child["ref_id"];
1278  }
1279  }
1280  */
1281 
1282  if (/* $cmode != ilLPObjSettings::LP_MODE_DEACTIVATED && */ $cmode != ilLPObjSettings::LP_MODE_UNDEFINED) {
1283  $a_object_ids[] = $child["obj_id"];
1284  $a_ref_ids[$child["obj_id"]] = $child["ref_id"];
1285  }
1286 
1287  self::getSubTree($child["ref_id"], $a_object_ids, $a_ref_ids);
1288  }
1289  }
1290  }
1291 
1302  public static function executeQueries(array $queries, $a_order_field = "", $a_order_dir = "", $a_offset = 0, $a_limit = 9999)
1303  {
1304  global $ilDB;
1305 
1306  $cnt = 0;
1307  $subqueries = array();
1308  foreach ($queries as $item) {
1309  // ugly "having" hack because of summary view
1310  $item = str_replace("[[--HAVING", "HAVING", $item);
1311  $item = str_replace("HAVING--]]", "", $item);
1312 
1313  if (!isset($item["count"])) {
1314  $count_field = $item["fields"];
1315  $count_field = array_shift($count_field);
1316  } else {
1317  $count_field = $item["count"];
1318  }
1319  $count_query = "SELECT COUNT(" . $count_field . ") AS cnt" . $item["query"];
1320  $set = $ilDB->query($count_query);
1321  if ($rec = $ilDB->fetchAssoc($set)) {
1322  $cnt += $rec["cnt"];
1323  }
1324 
1325  $subqueries[] = "SELECT " . implode(",", $item["fields"]) . $item["query"];
1326  }
1327 
1328  // set query
1329  $result = array();
1330  if ($cnt > 0) {
1331  if (sizeof($subqueries) > 1) {
1332  $base = array_shift($subqueries);
1333  $query = $base . " UNION (" . implode(") UNION (", $subqueries) . ")";
1334  } else {
1335  $query = $subqueries[0];
1336  }
1337 
1338  if ($a_order_dir != "asc" && $a_order_dir != "desc") {
1339  $a_order_dir = "asc";
1340  }
1341  if ($a_order_field) {
1342  $query.= " ORDER BY " . $a_order_field . " " . strtoupper($a_order_dir);
1343  }
1344 
1345  $offset = (int) $a_offset;
1346  $limit = (int) $a_limit;
1347  $ilDB->setLimit($limit, $offset);
1348 
1349  $set = $ilDB->query($query);
1350  while ($rec = $ilDB->fetchAssoc($set)) {
1351  $result[] = $rec;
1352  }
1353  }
1354 
1355  return array("cnt" => $cnt, "set" => $result);
1356  }
1357 
1369  public static function getUserObjectMatrix(
1370  $a_parent_ref_id,
1371  $a_obj_ids,
1372  $a_user_filter = null,
1373  array $a_additional_fields = null,
1374  array $a_privacy_fields = null,
1375  $a_check_agreement = null
1376  ) {
1377  global $ilDB;
1378 
1379  $result = array("cnt"=>0, "set"=>null);
1380  if (sizeof($a_obj_ids)) {
1381  $where = array();
1382  $where[] = "usr_data.usr_id <> " . $ilDB->quote(ANONYMOUS_USER_ID, "integer");
1383  if ($a_user_filter) {
1384  $where[] = $ilDB->like("usr_data.login", "text", "%" . $a_user_filter . "%");
1385  }
1386 
1387  // users
1388  $left = "";
1389  $a_users = self::getParticipantsForObject($a_parent_ref_id);
1390  if (is_array($a_users)) {
1391  $left = "LEFT";
1392  $where[] = $ilDB->in("usr_data.usr_id", $a_users, false, "integer");
1393  }
1394 
1395  $parent_obj_id = ilObject::_lookupObjectId($a_parent_ref_id);
1396  self::refreshObjectsStatus($a_obj_ids, $a_users);
1397 
1398  $fields = array("usr_data.usr_id", "login", "active");
1399  $udf = self::buildColumns($fields, $a_additional_fields);
1400 
1401  include_once("./Services/Tracking/classes/class.ilLPStatus.php");
1402 
1403  // #18673 - if parent supports percentage does not matter for "sub-items"
1404  $fields[] = "percentage";
1405 
1406  $raw = array();
1407  foreach ($a_obj_ids as $obj_id) {
1408  // one request for each object
1409  $query = " FROM usr_data " . $left . " JOIN read_event ON (read_event.usr_id = usr_data.usr_id" .
1410  " AND read_event.obj_id = " . $ilDB->quote($obj_id, "integer") . ")" .
1411  " LEFT JOIN ut_lp_marks ON (ut_lp_marks.usr_id = usr_data.usr_id " .
1412  " AND ut_lp_marks.obj_id = " . $ilDB->quote($obj_id, "integer") . ")" .
1413  " LEFT JOIN usr_pref ON (usr_pref.usr_id = usr_data.usr_id AND keyword = " . $ilDB->quote("language", "text") . ")" .
1414  self::buildFilters($where);
1415 
1416  $raw = self::executeQueries(array(array("fields"=>$fields, "query"=>$query)), "login");
1417  if ($raw["cnt"]) {
1418  // convert to final structure
1419  foreach ($raw["set"] as $row) {
1420  $result["set"][$row["usr_id"]]["login"] = $row["login"];
1421  $result["set"][$row["usr_id"]]["usr_id"] = $row["usr_id"];
1422 
1423  // #14953
1424  $result["set"][$row["usr_id"]]["obj_" . $obj_id] = $row["status"];
1425  $result["set"][$row["usr_id"]]["obj_" . $obj_id . "_perc"] = $row["percentage"];
1426 
1427  if ($obj_id == $parent_obj_id) {
1428  $result["set"][$row["usr_id"]]["status_changed"] = $row["status_changed"];
1429  $result["set"][$row["usr_id"]]["last_access"] = $row["last_access"];
1430  $result["set"][$row["usr_id"]]["spent_seconds"] = $row["spent_seconds"];
1431  $result["set"][$row["usr_id"]]["read_count"] = $row["read_count"];
1432  }
1433 
1434  foreach ($fields as $field) {
1435  // #14957 - value [as] language
1436  if (stristr($field, "language")) {
1437  $field = "language";
1438  }
1439 
1440  if (isset($row[$field])) {
1441  // #14955
1442  if ($obj_id == $parent_obj_id ||
1443  !in_array($field, array("mark", "u_comment"))) {
1444  $result["set"][$row["usr_id"]][$field] = $row[$field];
1445  }
1446  }
1447  }
1448  }
1449  }
1450  }
1451 
1452  $result["cnt"] = 0;
1453  if (is_array($result["set"])) {
1454  $result["cnt"] = count($result["set"]);
1455  }
1456  $result["users"] = $a_users;
1457 
1458  self::getUDFAndHandlePrivacy($result, $udf, $a_check_agreement, $a_privacy_fields, $a_additional_fields);
1459  }
1460  return $result;
1461  }
1462 
1463  public static function getUserObjectiveMatrix($a_parent_obj_id, $a_users)
1464  {
1465  global $ilDB;
1466 
1467  if ($a_parent_obj_id && $a_users) {
1468  $res = array();
1469 
1470  include_once "Services/Tracking/classes/class.ilLPStatus.php";
1471  include_once "Modules/Course/classes/Objectives/class.ilLOUserResults.php";
1472  include_once "Modules/Course/classes/class.ilCourseObjective.php";
1473  $objective_ids = ilCourseObjective::_getObjectiveIds($a_parent_obj_id, true);
1474 
1475  // #17402 - are initital test(s) qualifying?
1476  include_once "Modules/Course/classes/Objectives/class.ilLOSettings.php";
1477  $lo_set = ilLOSettings::getInstanceByObjId($a_parent_obj_id);
1478  $initial_qualifying = $lo_set->isInitialTestQualifying();
1479 
1480  // there may be missing entries for any user / objective combination
1481  foreach ($objective_ids as $objective_id) {
1482  foreach ($a_users as $user_id) {
1483  $res[$user_id][$objective_id] = ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM;
1484  }
1485  }
1486 
1487  $query = "SELECT * FROM loc_user_results" .
1488  " WHERE " . $ilDB->in("objective_id", $objective_ids, "", "integer") .
1489  " AND " . $ilDB->in("user_id", $a_users, "", "integer");
1490  if (!(bool) $initial_qualifying) {
1491  $query .= " AND type = " . $ilDB->quote(ilLOUserResults::TYPE_QUALIFIED, "integer");
1492  }
1493  $query .= " ORDER BY type"; // qualified must come last!
1494  $set = $ilDB->query($query);
1495  while ($row = $ilDB->fetchAssoc($set)) {
1496  $objective_id = $row["objective_id"];
1497  $user_id = $row["user_id"];
1498 
1499  // if both initial and qualified, qualified will overwrite initial
1500 
1501  // #15873 - see ilLOUserResults::getObjectiveStatusForLP()
1502  if ($row["status"] == ilLOUserResults::STATUS_COMPLETED) {
1503  $res[$user_id][$objective_id] = ilLPStatus::LP_STATUS_COMPLETED_NUM;
1504  } elseif ($row["status"] == ilLOUserResults::STATUS_FAILED) {
1505  $res[$user_id][$objective_id] = $row["is_final"]
1508  }
1509  }
1510 
1511  return $res;
1512  }
1513  }
1514 
1515  public static function getObjectAccessStatistics(array $a_ref_ids, $a_year, $a_month = null)
1516  {
1517  global $ilDB;
1518 
1519  $obj_ids = array_keys($a_ref_ids);
1520 
1521  if ($a_month) {
1522  $column = "dd";
1523  } else {
1524  $column = "mm";
1525  }
1526 
1527  $res = array();
1528  $sql = "SELECT obj_id," . $column . ",SUM(read_count) read_count,SUM(childs_read_count) childs_read_count," .
1529  "SUM(spent_seconds) spent_seconds,SUM(childs_spent_seconds) childs_spent_seconds" .
1530  " FROM obj_stat" .
1531  " WHERE " . $ilDB->in("obj_id", $obj_ids, "", "integer") .
1532  " AND yyyy = " . $ilDB->quote($a_year, "integer");
1533  if ($a_month) {
1534  $sql .= " AND mm = " . $ilDB->quote($a_month, "integer");
1535  }
1536  $sql .= " GROUP BY obj_id," . $column;
1537  $set = $ilDB->query($sql);
1538  while ($row = $ilDB->fetchAssoc($set)) {
1539  $row["read_count"] += $row["childs_read_count"];
1540  $row["spent_seconds"] += $row["childs_spent_seconds"];
1541  $res[$row["obj_id"]][$row[$column]]["read_count"] += $row["read_count"];
1542  $res[$row["obj_id"]][$row[$column]]["spent_seconds"] += $row["spent_seconds"];
1543  }
1544 
1545 
1546  // add user data
1547 
1548  $sql = "SELECT obj_id," . $column . ",SUM(counter) counter" .
1549  " FROM obj_user_stat" .
1550  " WHERE " . $ilDB->in("obj_id", $obj_ids, "", "integer") .
1551  " AND yyyy = " . $ilDB->quote($a_year, "integer");
1552  if ($a_month) {
1553  $sql .= " AND mm = " . $ilDB->quote($a_month, "integer");
1554  }
1555  $sql .= " GROUP BY obj_id," . $column;
1556  $set = $ilDB->query($sql);
1557  while ($row = $ilDB->fetchAssoc($set)) {
1558  $res[$row["obj_id"]][$row[$column]]["users"] += $row["counter"];
1559  }
1560 
1561  return $res;
1562  }
1563 
1564  public static function getObjectTypeStatistics()
1565  {
1566  global $ilDB, $objDefinition;
1567 
1568  // re-use add new item selection (folder is not that important)
1569  $types = array_keys($objDefinition->getCreatableSubObjects("root", ilObjectDefinition::MODE_REPOSITORY));
1570 
1571  // repository
1572  include_once "Services/Tree/classes/class.ilTree.php";
1573  $tree = new ilTree(1);
1574  $sql = "SELECT " . $tree->table_obj_data . ".obj_id," . $tree->table_obj_data . ".type," .
1575  $tree->table_tree . "." . $tree->tree_pk . "," . $tree->table_obj_reference . ".ref_id" .
1576  " FROM " . $tree->table_tree .
1577  " " . $tree->buildJoin() .
1578  " WHERE " . $ilDB->in($tree->table_obj_data . ".type", $types, "", "text");
1579  $set = $ilDB->query($sql);
1580  $res = array();
1581  while ($row = $ilDB->fetchAssoc($set)) {
1582  $res[$row["type"]]["type"] = $row["type"];
1583  $res[$row["type"]]["references"]++;
1584  $res[$row["type"]]["objects"][] = $row["obj_id"];
1585  if ($row[$tree->tree_pk] < 0) {
1586  $res[$row["type"]]["deleted"]++;
1587  }
1588  }
1589 
1590  foreach ($res as $type => $values) {
1591  $res[$type]["objects"] = sizeof(array_unique($values["objects"]));
1592  }
1593 
1594  // portfolios (not part of repository)
1595  foreach (self::getPortfolios() as $obj_id) {
1596  $res["prtf"]["type"] = "prtf";
1597  $res["prtf"]["references"]++;
1598  $res["prtf"]["objects"]++;
1599  }
1600 
1601  foreach (self::getWorkspaceBlogs() as $obj_id) {
1602  $res["blog"]["type"] = "blog";
1603  $res["blog"]["references"]++;
1604  $res["blog"]["objects"]++;
1605  }
1606 
1607  return $res;
1608  }
1609 
1610  public static function getWorkspaceBlogs($a_title = null)
1611  {
1612  global $ilDB;
1613 
1614  $res = array();
1615 
1616  // blogs in workspace?
1617  $sql = "SELECT od.obj_id,oref.wsp_id,od.type" .
1618  " FROM tree_workspace wst" .
1619  " JOIN object_reference_ws oref ON (oref.wsp_id = wst.child)" .
1620  " JOIN object_data od ON (oref.obj_id = od.obj_id)" .
1621  " WHERE od.type = " . $ilDB->quote("blog", "text");
1622 
1623  if ($a_title) {
1624  $sql .= " AND " . $ilDB->like("od.title", "text", "%" . $a_title . "%");
1625  }
1626 
1627  $set = $ilDB->query($sql);
1628  while ($row = $ilDB->fetchAssoc($set)) {
1629  $res[] = $row["obj_id"];
1630  }
1631 
1632  return $res;
1633  }
1634 
1635  public static function getPortfolios($a_title = null)
1636  {
1637  global $ilDB;
1638 
1639  $res = array();
1640 
1641  $sql = "SELECT od.obj_id" .
1642  " FROM usr_portfolio prtf" .
1643  " JOIN object_data od ON (od.obj_id = prtf.id)";
1644 
1645  if ($a_title) {
1646  $sql .= " WHERE " . $ilDB->like("od.title", "text", "%" . $a_title . "%");
1647  }
1648 
1649  $set = $ilDB->query($sql);
1650  while ($row = $ilDB->fetchAssoc($set)) {
1651  $res[] = $row["obj_id"];
1652  }
1653 
1654  return $res;
1655  }
1656 
1657  public static function getObjectDailyStatistics(array $a_ref_ids, $a_year, $a_month = null)
1658  {
1659  global $ilDB;
1660 
1661  $obj_ids = array_keys($a_ref_ids);
1662 
1663  $res = array();
1664  $sql = "SELECT obj_id,hh,SUM(read_count) read_count,SUM(childs_read_count) childs_read_count," .
1665  "SUM(spent_seconds) spent_seconds,SUM(childs_spent_seconds) childs_spent_seconds" .
1666  " FROM obj_stat" .
1667  " WHERE " . $ilDB->in("obj_id", $obj_ids, "", "integer") .
1668  " AND yyyy = " . $ilDB->quote($a_year, "integer");
1669  if ($a_month) {
1670  $sql .= " AND mm = " . $ilDB->quote($a_month, "integer");
1671  }
1672  $sql .= " GROUP BY obj_id,hh";
1673  $set = $ilDB->query($sql);
1674  while ($row = $ilDB->fetchAssoc($set)) {
1675  $row["read_count"] += $row["childs_read_count"];
1676  $row["spent_seconds"] += $row["childs_spent_seconds"];
1677  $res[$row["obj_id"]][(int) $row["hh"]]["read_count"] += $row["read_count"];
1678  $res[$row["obj_id"]][(int) $row["hh"]]["spent_seconds"] += $row["spent_seconds"];
1679  }
1680  return $res;
1681  }
1682 
1683  public static function getObjectStatisticsMonthlySummary()
1684  {
1685  global $ilDB;
1686 
1687  $set = $ilDB->query("SELECT COUNT(*) AS COUNTER,yyyy,mm" .
1688  " FROM obj_stat" .
1689  " GROUP BY yyyy, mm" .
1690  " ORDER BY yyyy DESC, mm DESC");
1691  $res = array();
1692  while ($row = $ilDB->fetchAssoc($set)) {
1693  $res[] = array("month"=>$row["yyyy"] . "-" . $row["mm"],
1694  "count"=>$row["counter"]);
1695  }
1696  return $res;
1697  }
1698 
1699  public static function deleteObjectStatistics(array $a_months)
1700  {
1701  global $ilDB;
1702 
1703  // no combined column, have to concat
1704  $date_compare = $ilDB->in($ilDB->concat(array(array("yyyy", ""),
1705  array($ilDB->quote("-", "text"), ""),
1706  array("mm", ""))), $a_months, "", "text");
1707  $sql = "DELETE FROM obj_stat" .
1708  " WHERE " . $date_compare;
1709  $ilDB->manipulate($sql);
1710 
1711  // fulldate == YYYYMMDD
1712  $tables = array("obj_lp_stat", "obj_type_stat", "obj_user_stat");
1713  foreach ($a_months as $month) {
1714  $year = substr($month, 0, 4);
1715  $month = substr($month, 5);
1716  $from = $year . str_pad($month, 2, "0", STR_PAD_LEFT) . "01";
1717  $to = $year . str_pad($month, 2, "0", STR_PAD_LEFT) . "31";
1718 
1719  foreach ($tables as $table) {
1720  $sql = "DELETE FROM " . $table .
1721  " WHERE fulldate >= " . $ilDB->quote($from, "integer") .
1722  " AND fulldate <= " . $ilDB->quote($to, "integer");
1723  $ilDB->manipulate($sql);
1724  }
1725  }
1726  }
1727 
1728  public static function searchObjects($a_type, $a_title = null, $a_root = null, $a_hidden = null, $a_preset_obj_ids = null)
1729  {
1730  global $ilDB, $tree;
1731 
1732  if ($a_type == "lres") {
1733  $a_type = array('lm','sahs','htlm');
1734  }
1735 
1736  $sql = "SELECT r.ref_id,r.obj_id" .
1737  " FROM object_data o" .
1738  " JOIN object_reference r ON (o.obj_id = r.obj_id)" .
1739  " JOIN tree t ON (t.child = r.ref_id)" .
1740  " WHERE t.tree = " . $ilDB->quote(1, "integer");
1741 
1742  if (!is_array($a_type)) {
1743  $sql .= " AND o.type = " . $ilDB->quote($a_type, "text");
1744  } else {
1745  $sql .= " AND " . $ilDB->in("o.type", $a_type, "", "text");
1746  }
1747 
1748  if ($a_title) {
1749  $sql .= " AND (" . $ilDB->like("o.title", "text", "%" . $a_title . "%") .
1750  " OR " . $ilDB->like("o.description", "text", "%" . $a_title . "%") . ")";
1751  }
1752 
1753  if (is_array($a_hidden)) {
1754  $sql .= " AND " . $ilDB->in("o.obj_id", $a_hidden, true, "integer");
1755  }
1756 
1757  if (is_array($a_preset_obj_ids)) {
1758  $sql .= " AND " . $ilDB->in("o.obj_id", $a_preset_obj_ids, false, "integer");
1759  }
1760 
1761  $set = $ilDB->query($sql);
1762  $res = array();
1763  while ($row = $ilDB->fetchAssoc($set)) {
1764  if ($a_root && $a_root != ROOT_FOLDER_ID) {
1765  foreach (ilObject::_getAllReferences($row['obj_id']) as $ref_id) {
1766  if ($tree->isGrandChild($a_root, $ref_id)) {
1767  $res[$row["obj_id"]][] = $row["ref_id"];
1768  continue;
1769  }
1770  }
1771  } else {
1772  $res[$row["obj_id"]][] = $row["ref_id"];
1773  }
1774  }
1775  return $res;
1776  }
1777 
1784  protected static function refreshObjectsStatus(array $a_obj_ids, $a_users = null)
1785  {
1786  include_once("./Services/Tracking/classes/class.ilLPStatus.php");
1787  foreach ($a_obj_ids as $obj_id) {
1788  ilLPStatus::checkStatusForObject($obj_id, $a_users);
1789  }
1790  }
1791 
1797  public static function getObjectStatisticsLogInfo()
1798  {
1799  global $ilDB;
1800 
1801  $set = $ilDB->query("SELECT COUNT(*) counter, MIN(tstamp) tstamp" .
1802  " FROM obj_stat_log");
1803  return $ilDB->fetchAssoc($set);
1804  }
1805 
1806  public static function getObjectLPStatistics(array $a_obj_ids, $a_year, $a_month = null, $a_group_by_day = false)
1807  {
1808  global $ilDB;
1809 
1810  if ($a_group_by_day) {
1811  $column = "dd";
1812  } else {
1813  $column = "mm,yyyy";
1814  }
1815 
1816  $res = array();
1817  $sql = "SELECT obj_id," . $column . "," .
1818  "MIN(mem_cnt) mem_cnt_min,AVG(mem_cnt) mem_cnt_avg, MAX(mem_cnt) mem_cnt_max," .
1819  "MIN(in_progress) in_progress_min,AVG(in_progress) in_progress_avg,MAX(in_progress) in_progress_max," .
1820  "MIN(completed) completed_min,AVG(completed) completed_avg,MAX(completed) completed_max," .
1821  "MIN(failed) failed_min,AVG(failed) failed_avg,MAX(failed) failed_max," .
1822  "MIN(not_attempted) not_attempted_min,AVG(not_attempted) not_attempted_avg,MAX(not_attempted) not_attempted_max" .
1823  " FROM obj_lp_stat" .
1824  " WHERE " . $ilDB->in("obj_id", $a_obj_ids, "", "integer") .
1825  " AND yyyy = " . $ilDB->quote($a_year, "integer");
1826  if ($a_month) {
1827  $sql .= " AND mm = " . $ilDB->quote($a_month, "integer");
1828  }
1829  $sql .= " GROUP BY obj_id," . $column;
1830  $set = $ilDB->query($sql);
1831  while ($row = $ilDB->fetchAssoc($set)) {
1832  $res[] = $row;
1833  }
1834 
1835  return $res;
1836  }
1837 
1838  public static function getObjectTypeStatisticsPerMonth($a_aggregation, $a_year = null)
1839  {
1840  global $ilDB;
1841 
1842  if (!$a_year) {
1843  $a_year = date("Y");
1844  }
1845 
1846  $agg = strtoupper($a_aggregation);
1847 
1848  $res = array();
1849  $sql = "SELECT type,yyyy,mm," . $agg . "(cnt_objects) cnt_objects," . $agg . "(cnt_references) cnt_references," .
1850  "" . $agg . "(cnt_deleted) cnt_deleted FROM obj_type_stat" .
1851  " WHERE yyyy = " . $ilDB->quote($a_year, "integer") .
1852  " GROUP BY type,yyyy,mm";
1853  $set = $ilDB->query($sql);
1854  while ($row = $ilDB->fetchAssoc($set)) {
1855  $row["mm"] = str_pad($row["mm"], 2, "0", STR_PAD_LEFT);
1856  $res[$row["type"]][$row["yyyy"] . "-" . $row["mm"]] = array(
1857  "objects" => (int) $row["cnt_objects"],
1858  "references" => (int) $row["cnt_references"],
1859  "deleted" => (int) $row["cnt_deleted"]
1860  );
1861  }
1862 
1863  return $res;
1864  }
1865 }
const LP_STATUS_COMPLETED_NUM
static getObjectiveStatusForLP($a_user_id, $a_obj_id, array $a_objective_ids)
static refreshObjectsStatus(array $a_obj_ids, $a_users=null)
check whether status (for all relevant users) exists
static getInstanceByObjId($a_obj_id)
get singleton instance
static getObjectLPStatistics(array $a_obj_ids, $a_year, $a_month=null, $a_group_by_day=false)
const IL_CRS_VIEW_OBJECTIVE
For the purpose of streamlining the grading and learning-process status definition outside of tests...
const IL_CAL_DATETIME
Class ilExerciseMembers.
$result
$type
static executeQueries(array $queries, $a_order_field="", $a_order_dir="", $a_offset=0, $a_limit=9999)
Execute given queries, including count query.
static checkStatusForObject($a_obj_id, $a_users=false)
This function checks whether the status for a given number of users is dirty and must be recalculated...
static getObjectStatisticsMonthlySummary()
const LP_STATUS_NOT_ATTEMPTED
static getUserDataForObject( $a_ref_id, $a_order_field="", $a_order_dir="", $a_offset=0, $a_limit=9999, array $a_filters=null, array $a_additional_fields=null, $check_agreement=false, $privacy_fields=null)
Get all user-based tracking data for object.
$valid
static getSubItemType($a_parent_obj_id)
Get sub-item object type for parent.
static deleteObjectStatistics(array $a_months)
$session
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
const LP_STATUS_IN_PROGRESS_NUM
if(!array_key_exists('StateId', $_REQUEST)) $id
static _getObjectiveIds($course_id, $a_activated_only=false)
static getSummaryDataForObject($a_ref_id, array $fields, array $a_filters=null)
Get all aggregated tracking data for object.
$from
static getUDFAndHandlePrivacy(array &$a_result, array $a_udf=null, $a_check_agreement=null, array $a_privacy_fields=null, array $a_filters=null)
Handle privacy and add udf data to (user) result data.
static getObjectsStatusForUser($a_user_id, array $obj_refs)
static getSummaryPercentages($field, $base_query, $alias=null)
Get aggregated data for field.
static _getInstance($a_obj_id, $a_mode=null)
const IL_CAL_UNIX
static _getTrackedUsers($a_obj_id)
Get all tracked users.
static _lookupSubType($a_obj_id)
lookup subtype id (scorm, )
static _getAllReferences($a_id)
get all reference ids of object
static _getClassById($a_obj_id, $a_mode=null)
const LP_STATUS_IN_PROGRESS
if($modEnd===false) $module
Definition: module.php:59
static _lookupObjectId($a_ref_id)
lookup object id
Tracking query class.
$base
Definition: index.php:4
static getInstance($a_ref_id)
Get instance by ref_id.
$time
Definition: cron.php:21
static getObjectDailyStatistics(array $a_ref_ids, $a_year, $a_month=null)
$a_type
Definition: workflow.php:92
Class ilObjExercise.
static getSCOsStatusForUser($a_user_id, $a_parent_obj_id, array $a_sco_ids)
const LP_STATUS_FAILED
$column
Definition: 39dropdown.php:62
foreach($_POST as $key=> $value) $res
static getSubTree($a_parent_ref_id, array &$a_object_ids, array &$a_ref_ids)
Get complete branch of tree (recursively)
static getSubItemsStatusForUser($a_user_id, $a_parent_obj_id, array $a_item_ids)
Get subitems status.
static stableSortArray($array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false)
Sort an aray using a stable sort algorithm, which preveserves the sequence of array elements which ha...
static buildColumns(array &$a_fields, array $a_additional_fields=null, $a_aggregate=false)
Build sql from field definition.
static getObjectAccessStatistics(array $a_ref_ids, $a_year, $a_month=null)
Class ilObjStudyProgramme.
static _lookupObjId($a_id)
date( 'd-M-Y', $objPHPExcel->getProperties() ->getCreated())
Date and time handling
static getSessionData($a_user_id, array $obj_ids)
Get session data for given objects and user.
$query
static getObjectsSummaryForObject( $a_parent_obj_id, $a_parent_ref_id, $a_order_field="", $a_order_dir="", $a_offset=0, $a_limit=9999, array $a_filters=null, array $a_additional_fields=null, $a_preselected_obj_ids=null)
Get all aggregated tracking data for parent object.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
Create styles array
The data for the language used.
static _lookupType($a_id, $a_reference=false)
lookup object type
static _getStatusInfo($a_obj_id)
Reads informations about the object e.g test results, tlt, number of visits.
static getObjectIds($a_parent_obj_id, $a_parent_ref_id=false, $use_collection=true, $a_refresh_status=true, $a_user_ids=null)
Get (sub)objects for given object, also handles learning objectives (course only) ...
static getUserObjectiveMatrix($a_parent_obj_id, $a_users)
const LP_STATUS_NOT_ATTEMPTED_NUM
static getObjectivesStatusForUser($a_user_id, $a_obj_id, array $a_objective_ids)
static formatPeriod(ilDateTime $start, ilDateTime $end, $a_skip_starting_day=false)
Format a period of two date Shows: 14.
static getObjectTypeStatisticsPerMonth($a_aggregation, $a_year=null)
static getParticipantsForObject($a_ref_id)
Get participant ids for given object.
static searchObjects($a_type, $a_title=null, $a_root=null, $a_hidden=null, $a_preset_obj_ids=null)
static getObjectsDataForUser( $a_user_id, $a_parent_obj_id, $a_parent_ref_id, $a_order_field="", $a_order_dir="", $a_offset=0, $a_limit=9999, array $a_filters=null, array $a_additional_fields=null, $use_collection=true)
Get all object-based tracking data for user and parent object.
static getPortfolios($a_title=null)
Class ilObjSCORM2004LearningModule.
global $ilDB
$function
Definition: cas.php:28
static getWorkspaceBlogs($a_title=null)
static getUserObjectMatrix( $a_parent_ref_id, $a_obj_ids, $a_user_filter=null, array $a_additional_fields=null, array $a_privacy_fields=null, $a_check_agreement=null)
Get status matrix for users on objects.
static buildFilters(array $where, array $a_filters=null, $a_aggregate=false)
Build sql from filter definition.
static getObjectTypeStatistics()
if(empty($password)) $table
Definition: pwgen.php:24
const LP_STATUS_COMPLETED
static getInstance($a_obj_id)
Class ilObjSCORMLearningModule.
static lookupAcceptedAgreements($a_obj_id)
Lookup users who have accepted the agreement.
static getObjectStatisticsLogInfo()
Get last update info for object statistics.
const LP_STATUS_FAILED_NUM