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