ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
class.ilObjectLP.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 include_once "Services/Tracking/classes/class.ilLPObjSettings.php";
6 
15 {
16  protected $obj_id; // [int]
17  protected $collection_instance; // [ilLPCollection]
18  protected $mode; // [int]
19 
20  protected static $type_defaults; // [array]
21 
22  protected function __construct($a_obj_id)
23  {
24  $this->obj_id = (int)$a_obj_id;
25  }
26 
27  public static function getInstance($a_obj_id)
28  {
29  static $instances = array();
30 
31  if(!isset($instances[$a_obj_id]))
32  {
33  $type = ilObject::_lookupType($a_obj_id);
34  $class = self::getTypeClass($type);
35  if($class)
36  {
37  $instance = new $class($a_obj_id);
38  }
39  else
40  {
41  // :TODO: should we return anything?
42  $instance = new self($a_obj_id);
43  }
44  $instances[$a_obj_id] = $instance;
45  }
46 
47  return $instances[$a_obj_id];
48  }
49 
50  public static function getTypeClass($a_type)
51  {
52  global $objDefinition;
53 
54  if(self::isSupportedObjectType($a_type))
55  {
56  switch($a_type)
57  {
58  // container
59 
60  case "crs":
61  include_once "Modules/Course/classes/class.ilCourseLP.php";
62  return "ilCourseLP";
63 
64  case "grp":
65  include_once "Modules/Group/classes/class.ilGroupLP.php";
66  return "ilGroupLP";
67 
68  case "fold":
69  include_once "Modules/Folder/classes/class.ilFolderLP.php";
70  return "ilFolderLP";
71 
72 
73  // learning resources
74 
75  case "lm":
76  include_once "Modules/LearningModule/classes/class.ilLearningModuleLP.php";
77  return "ilLearningModuleLP";
78 
79  case "htlm":
80  include_once "Modules/HTMLLearningModule/classes/class.ilHTMLLearningModuleLP.php";
81  return "ilHTMLLearningModuleLP";
82 
83  case "sahs":
84  include_once "Modules/ScormAicc/classes/class.ilScormLP.php";
85  return "ilScormLP";
86 
87 
88  // misc
89 
90  case "tst":
91  include_once "Modules/Test/classes/class.ilTestLP.php";
92  return "ilTestLP";
93 
94  case "exc":
95  include_once "Modules/Exercise/classes/class.ilExerciseLP.php";
96  return "ilExerciseLP";
97 
98  case 'file':
99  require_once 'Modules/File/classes/class.ilFileLP.php';
100  return 'ilFileLP';
101 
102  case "mcst":
103  require_once "Modules/MediaCast/classes/class.ilMediaCastLP.php";
104  return "ilMediaCastLP";
105 
106  case "sess":
107  include_once "Modules/Session/classes/class.ilSessionLP.php";
108  return "ilSessionLP";
109 
110  case "svy":
111  include_once "Modules/Survey/classes/class.ilSurveyLP.php";
112  return "ilSurveyLP";
113 
114  case "prg":
115  include_once "Modules/StudyProgramme/classes/class.ilStudyProgrammeLP.php";
116  return "ilStudyProgrammeLP";
117 
118  case "iass":
119  include_once "Modules/IndividualAssessment/classes/class.ilIndividualAssessmentLP.php";
120  return "ilIndividualAssessmentLP";
121 
122  // plugin
123  case $objDefinition->isPluginTypeName($a_type):
124  include_once "Services/Component/classes/class.ilPluginLP.php";
125  return "ilPluginLP";
126  }
127  }
128  }
129 
130  public static function isSupportedObjectType($a_type)
131  {
132  global $objDefinition;
133 
134  $valid = array("crs", "grp", "fold", "lm", "htlm", "sahs", "tst", "exc", "sess", "svy", "file", "mcst", "prg", "iass");
135 
136  if(in_array($a_type, $valid))
137  {
138  return true;
139  }
140 
141  if($objDefinition->isPluginTypeName($a_type))
142  {
143  include_once 'Services/Repository/classes/class.ilRepositoryObjectPluginSlot.php';
145  }
146 
147  return false;
148  }
149 
150  public function resetCaches()
151  {
152  $this->mode = null;
153  $this->collection_instance = null;
154  }
155 
156  public function isAnonymized()
157  {
158  // see ilLPCollectionOfRepositoryObjects::validateEntry()
159  return false;
160  }
161 
162 
163  //
164  // MODE
165  //
166 
167  public function getDefaultMode()
168  {
169 
171  }
172 
173  public function getValidModes()
174  {
175  return array();
176  }
177 
178  public function getCurrentMode()
179  {
180  if($this->mode === null)
181  {
182  // using global type default if LP is inactive
183  include_once "Services/Tracking/classes/class.ilObjUserTracking.php";
185  {
186  $mode = self::getTypeDefaultFromDB(ilObject::_lookupType($this->obj_id));
187  if($mode === null)
188  {
189  // fallback: inactive as type default may not be suitable
191  }
192  }
193  // use object LP setting
194  else
195  {
196  $mode = ilLPObjSettings::_lookupDBMode($this->obj_id);
197  if($mode === null)
198  {
199  // fallback: object type default
200  $mode = $this->getDefaultMode();
201  }
202  }
203  $this->mode = (int)$mode;
204  }
205 
206  return $this->mode;
207  }
208 
209  public function isActive()
210  {
211  // :TODO: check LP activation?
212 
213  $mode = $this->getCurrentMode();
216  {
217  return false;
218  }
219  return true;
220  }
221 
222  public function getModeText($a_mode)
223  {
224  return ilLPObjSettings::_mode2Text($a_mode);
225  }
226 
227  public function getModeInfoText($a_mode)
228  {
229  return ilLPObjSettings::_mode2InfoText($a_mode);
230  }
231 
232  public function getSettingsInfo()
233  {
234  // type-specific
235  }
236 
237 
238  //
239  // COLLECTION
240  //
241 
242  public function getCollectionInstance()
243  {
244  if($this->collection_instance === null)
245  {
246  include_once "Services/Tracking/classes/collection/class.ilLPCollection.php";
247  $this->collection_instance = ilLPCollection::getInstanceByMode($this->obj_id, $this->getCurrentMode());
248  }
249 
251  }
252 
253 
254  //
255  // MEMBERS
256  //
257 
258  public function getMembers($a_search = true)
259  {
260  global $tree;
261 
262  if(!$a_search)
263  {
264  return;
265  }
266 
267  $ref_ids = ilObject::_getAllReferences($this->obj_id);
268  $ref_id = current($ref_ids);
269 
270  // walk path to find parent with specific members
271  $path = $tree->getPathId($ref_id);
272  array_pop($path);
273  foreach(array_reverse($path) as $path_ref_id)
274  {
275  $olp = self::getInstance(ilObject::_lookupObjId($path_ref_id));
276  $all = $olp->getMembers(false);
277  if(is_array($all))
278  {
279  return $all;
280  }
281  }
282  }
283 
284 
285  //
286  // RESET
287  //
288 
289  final public function resetLPDataForCompleteObject($a_recursive = true)
290  {
291  $user_ids = $this->gatherLPUsers();
292  if(sizeof($user_ids))
293  {
294  $this->resetLPDataForUserIds(array_unique($user_ids), $a_recursive);
295  }
296  }
297 
298  final public function resetLPDataForUserIds(array $a_user_ids, $a_recursive = true)
299  {
300  if((bool)$a_recursive &&
301  method_exists($this, "getPossibleCollectionItems")) // #15203
302  {
303  $subitems = $this->getPossibleCollectionItems();
304  if(is_array($subitems))
305  {
306  foreach($subitems as $sub_ref_id)
307  {
308  $olp = self::getInstance(ilObject::_lookupObjId($sub_ref_id));
309  $olp->resetLPDataForUserIds($a_user_ids, false);
310  }
311  }
312  }
313 
314  $this->resetCustomLPDataForUserIds($a_user_ids, (bool)$a_recursive);
315 
316  include_once "Services/Tracking/classes/class.ilLPMarks.php";
317  ilLPMarks::_deleteForUsers($this->obj_id, $a_user_ids);
318 
319  include_once "Services/Tracking/classes/class.ilChangeEvent.php";
320  ilChangeEvent::_deleteReadEventsForUsers($this->obj_id, $a_user_ids);
321 
322  // update LP status to get collections up-to-date
323  include_once "Services/Tracking/classes/class.ilLPStatusWrapper.php";
324  foreach($a_user_ids as $user_id)
325  {
326  ilLPStatusWrapper::_updateStatus($this->obj_id, $user_id);
327  }
328  }
329 
330  protected function resetCustomLPDataForUserIds(array $a_user_ids, $a_recursive = true)
331  {
332  // this should delete all data that is relevant for the supported LP modes
333  }
334 
335  protected function gatherLPUsers()
336  {
337  include_once "Services/Tracking/classes/class.ilLPMarks.php";
338  $user_ids = ilLPMarks::_getAllUserIds($this->obj_id);
339 
340  include_once "Services/Tracking/classes/class.ilChangeEvent.php";
341  $user_ids = array_merge($user_ids, ilChangeEvent::_getAllUserIds($this->obj_id));
342 
343  return $user_ids;
344  }
345 
346 
347  //
348  // EVENTS
349  //
350 
351  final static public function handleMove($a_source_ref_id)
352  {
353  global $tree, $ilDB;
354 
355  $ref_ids = $tree->getSubTreeIds($a_source_ref_id);
356  $ref_ids[] = $a_source_ref_id;
357 
358  // get "parent" path to source node (not including source node)
359  $new_path = $tree->getPathId($a_source_ref_id);
360  array_pop($new_path);
361  $new_path = implode("/", $new_path);
362 
363  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
364 
365  // find collections with ref_ids
366  $set = $ilDB->query("SELECT DISTINCT(ut_lp_collections.obj_id) obj_id".
367  " FROM object_reference".
368  " JOIN ut_lp_collections ON".
369  " (".$ilDB->in("object_reference.ref_id", $ref_ids, "", "integer").
370  " AND object_reference.ref_id = ut_lp_collections.item_id)");
371  while ($rec = $ilDB->fetchAssoc($set))
372  {
373  if (in_array(ilObject::_lookupType($rec["obj_id"]), array("crs", "grp", "fold")))
374  {
375  $coll_ref_id = ilObject::_getAllReferences($rec["obj_id"]);
376  $coll_ref_id = array_pop($coll_ref_id);
377 
378  // #13402
379  if($coll_ref_id == $a_source_ref_id)
380  {
381  continue;
382  }
383 
384  // #17703 - collection has also been moved - nothing todo
385  if($tree->isGrandChild($a_source_ref_id, $coll_ref_id))
386  {
387  continue;
388  }
389 
390  // get path to collection (including collection "parent")
391  $coll_path = $tree->getPathId($coll_ref_id);
392  $coll_path = implode("/", $coll_path);
393 
394  // collection path is not inside new path
395  if(!stristr($new_path, $coll_path))
396  {
397  // delete all items of moved (sub-)tree
398  $query = "DELETE FROM ut_lp_collections".
399  " WHERE obj_id = ".$ilDB->quote($rec["obj_id"], "integer").
400  " AND ".$ilDB->in("item_id", $ref_ids, "", "integer");
401  $ilDB->manipulate($query);
402 
403  ilLPStatusWrapper::_refreshStatus($rec["obj_id"]);
404  }
405  }
406  }
407  }
408 
409  final public function handleToTrash()
410  {
411  $this->updateParentCollections();
412  }
413 
414  final public function handleDelete()
415  {
416  include_once "Services/Tracking/classes/class.ilLPMarks.php";
417  ilLPMarks::deleteObject($this->obj_id);
418 
419  include_once "Services/Tracking/classes/class.ilChangeEvent.php";
420  ilChangeEvent::_delete($this->obj_id);
421 
422  $collection = $this->getCollectionInstance();
423  if($collection)
424  {
425  $collection->delete();
426  }
427 
428  $this->updateParentCollections();
429  }
430 
431  final protected function updateParentCollections()
432  {
433  global $ilDB;
434 
435  include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
436 
437  // update parent collections?
438  $set = $ilDB->query("SELECT ut_lp_collections.obj_id obj_id FROM ".
439  "object_reference JOIN ut_lp_collections ON ".
440  "(object_reference.obj_id = ".$ilDB->quote($this->obj_id, "integer").
441  " AND object_reference.ref_id = ut_lp_collections.item_id)");
442  while ($rec = $ilDB->fetchAssoc($set))
443  {
444  if (in_array(ilObject::_lookupType($rec["obj_id"]), array("crs", "grp", "fold")))
445  {
446  // remove from parent collection
447  $query = "DELETE FROM ut_lp_collections".
448  " WHERE obj_id = ".$ilDB->quote($rec["obj_id"], "integer").
449  " AND item_id = ".$ilDB->quote($this->obj_id, "integer");
450  $ilDB->manipulate($query);
451 
452  ilLPStatusWrapper::_refreshStatus($rec["obj_id"]);
453  }
454  }
455  }
456 
457 
458  //
459  // LP-relevant memberships
460  //
461 
469  protected static function isLPMember(array &$a_res, $a_usr_id, $a_obj_ids)
470  {
471  // should be overwritten by object-type-specific class
472  return false;
473  }
474 
485  protected static function findMembershipsByPath(array &$a_res, $a_usr_id, $a_parent_ref_id, array $a_obj_ids, $a_mapped_ref_ids = false)
486  {
487  global $tree;
488 
489  $found = array();
490 
491  // walk path to find course or group object and check members of that object
492  $path = $tree->getPathId($a_parent_ref_id);
493  foreach(array_reverse($path) as $path_ref_id)
494  {
495  $type = ilObject::_lookupType($path_ref_id, true);
496  if($type == "crs" ||
497  $type == "grp")
498  {
499  $class = self::getTypeClass($type);
500  $path_ob_id = ilObject::_lookupObjId($path_ref_id);
501  $chk = array();
502  $class::isLPMember($chk, $a_usr_id, array($path_ob_id));
503  if(!$a_mapped_ref_ids)
504  {
505  // we found a grp/crs in path of (single) parent - mark all objects
506  foreach($a_obj_ids as $obj_id)
507  {
508  $found[] = $obj_id;
509  if($chk[$path_ob_id])
510  {
511  $a_res[$obj_id] = true;
512  }
513  }
514  }
515  else
516  {
517  // all children from current node are "lp-valid"
518  foreach($a_obj_ids as $obj_id => $ref_ids)
519  {
520  foreach($ref_ids as $ref_id)
521  {
522  if($tree->isGrandChild($path_ref_id, $ref_id))
523  {
524  $found[$obj_id][] = $ref_id;
525  if($chk[$path_ob_id])
526  {
527  $a_res[$obj_id] = true;
528  }
529  break;
530  }
531  }
532  }
533  }
534  break;
535  }
536  }
537 
538  return $found;
539  }
540 
550  public static function getLPMemberships($a_usr_id, array $a_obj_ids, $a_parent_ref_id = null, $a_mapped_ref_ids = false)
551  {
552  global $ilDB, $tree;
553 
554  // see ilTrQuery::getParticipantsForObject() [single object only]
555  // this is optimized for larger number of objects, e.g. list GUIs
556 
557  if((bool)$a_mapped_ref_ids)
558  {
559  $ref_map = $a_obj_ids;
560  $a_obj_ids = array_keys($a_obj_ids);
561  }
562 
563  $res = array();
564 
565  // get object types
566  $types_map = array();
567  $query = " SELECT obj_id, type".
568  " FROM object_data".
569  " WHERE ".$ilDB->in("obj_id", $a_obj_ids, "", "integer");
570  $set = $ilDB->query($query);
571  while($row = $ilDB->fetchAssoc($set))
572  {
573  $types_map[$row["type"]][] = $row["obj_id"];
574  $res[$row["obj_id"]] = false;
575  }
576 
577  $find_by_parent = array();
578  foreach($types_map as $type => $type_obj_ids)
579  {
580  $class = self::getTypeClass($type);
581  if($class)
582  {
583  // lp-supported type?
584  if(!$class::isLPMember($res, $a_usr_id, $type_obj_ids))
585  {
586  $find_by_parent = array_merge($find_by_parent, $type_obj_ids);
587  }
588  }
589  }
590 
591  if(sizeof($find_by_parent))
592  {
593  // single parent for all objects (repository/ilObjectListGUI)
594  if($a_parent_ref_id)
595  {
596  if(self::findMembershipsByPath($res, $a_usr_id, $a_parent_ref_id, $find_by_parent))
597  {
598  // we found a crs/grp in path, so no need to check read_events
599  $find_by_parent = null;
600  }
601  }
602  // different parents (PD > LP)
603  else if(sizeof($ref_map))
604  {
605  foreach($find_by_parent as $obj_id)
606  {
607  // maybe already found by path search from other object/reference
608  if($res[$obj_id] === false)
609  {
610  if(isset($ref_map[$obj_id]))
611  {
612  // check all references
613  foreach($ref_map[$obj_id] as $ref_id)
614  {
615  $parent_ref_id = $tree->getParentId($ref_id);
616  if($parent_ref_id == ROOT_FOLDER_ID)
617  {
618  continue;
619  }
620 
621  // we are checking the complete ref_map
622  // to find all relevant objects in subtree of current ref_id
623  $found = self::findMembershipsByPath($res, $a_usr_id, $parent_ref_id, $ref_map, true);
624  if(sizeof($found))
625  {
626  // if any references were found in a crs/grp-subtree
627  // remove from "read-event"-last-resort-pool
628  foreach($found as $found_obj_id => $found_ref_ids)
629  {
630  $diff = array_diff($ref_map[$found_obj_id], $found_ref_ids);
631  if($diff)
632  {
633  // 1-n refs are in another subtree
634  // have to be checked separately
635  $ref_map[$found_obj_id] = $diff;
636  }
637  else
638  {
639  // all references found in subtree
640  // no need to check again
641  unset($ref_map[$found_obj_id]);
642  }
643  }
644  break;
645  }
646  }
647  }
648  }
649  }
650 
651  $find_by_parent = array_keys($ref_map);
652  }
653 
654  // last resort: use read_event?
655  if(sizeof($find_by_parent))
656  {
657  $set = $ilDB->query("SELECT obj_id".
658  " FROM read_event".
659  " WHERE ".$ilDB->in("obj_id", $find_by_parent, "", "integer").
660  " AND usr_id = ".$ilDB->quote($a_usr_id, "integer"));
661  while($row = $ilDB->fetchAssoc($set))
662  {
663  $res[$row["obj_id"]] = true;
664  }
665  }
666  }
667 
668  return $res;
669  }
670 
671  public function getMailTemplateId()
672  {
673  // type-specific
674  }
675 
676 
677  //
678  // type-specific support of features (should be enhanced)
679  //
680 
681  public static function supportsSpentSeconds($a_obj_type)
682  {
683  return !in_array($a_obj_type, array("exc", "file", "mcst", "mob", "htlm"));
684  }
685 
686  public static function supportsMark($a_obj_type)
687  {
688  return !in_array($a_obj_type, array("lm", "dbk"));
689  }
690 
691  public static function supportsMatrixView($a_obj_type)
692  {
693  return !in_array($a_obj_type, array('svy', 'tst', 'htlm', 'exc', 'sess', 'file', 'prg'));
694  }
695 
696 
697  // type-wide default
698 
704  public static function getDefaultModes($a_lp_active)
705  {
707  }
708 
709  protected static function getTypeDefaultFromDB($a_type)
710  {
711  global $ilDB;
712 
713  if(!is_array(self::$type_defaults))
714  {
715  self::$type_defaults = array();
716  $set = $ilDB->query("SELECT * FROM ut_lp_defaults");
717  while($row = $ilDB->fetchAssoc($set))
718  {
719  self::$type_defaults[$row["type_id"]] = $row["lp_mode"];
720  }
721  }
722  return self::$type_defaults[$a_type];
723  }
724 
725  public static function saveTypeDefaults(array $a_data)
726  {
727  global $ilDB;
728 
729  $ilDB->manipulate("DELETE FROM ut_lp_defaults");
730  foreach($a_data as $type => $mode)
731  {
732  $ilDB->insert("ut_lp_defaults", array(
733  "type_id" => array("text", $type),
734  "lp_mode" => array("integer", $mode)
735  ));
736  }
737  }
738 
745  public static function getTypeDefault($a_type)
746  {
747  $db = self::getTypeDefaultFromDB($a_type);
748  if($db !== null)
749  {
750  return $db;
751  }
752 
753  $class = self::getTypeClass($a_type);
754  $olp = new $class(0);
755  return $olp->getDefaultMode();
756  }
757 }
758 
759 ?>
$path
Definition: aliased.php:25
static isTypePluginWithLP($a_type, $a_active_status=true)
Check whether a repository type is a plugin which has active learning progress.
static getTypeDefaultFromDB($a_type)
resetLPDataForUserIds(array $a_user_ids, $a_recursive=true)
static getTypeClass($a_type)
getModeInfoText($a_mode)
resetLPDataForCompleteObject($a_recursive=true)
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
static isSupportedObjectType($a_type)
$valid
static getInstanceByMode($a_obj_id, $a_mode)
static _getAllUserIds($a_obj_id)
static _refreshStatus($a_obj_id, $a_users=null)
Set dirty.
static _getAllUserIds($a_obj_id)
static _getAllReferences($a_id)
get all reference ids of object
__construct($a_obj_id)
resetCustomLPDataForUserIds(array $a_user_ids, $a_recursive=true)
$a_type
Definition: workflow.php:93
static getTypeDefault($a_type)
Get current type default.
static _enabledLearningProgress()
check wether learing progress is enabled or not
static _delete($a_obj_id)
Delete object entries.
static findMembershipsByPath(array &$a_res, $a_usr_id, $a_parent_ref_id, array $a_obj_ids, $a_mapped_ref_ids=false)
Find (lp-relevant) memberships by path.
static _lookupDBMode($a_obj_id)
static _lookupObjId($a_id)
static saveTypeDefaults(array $a_data)
static $type_defaults
static getDefaultModes($a_lp_active)
Get available type-specific default modes (no administration needed)
static _deleteForUsers($a_obj_id, array $a_user_ids)
static supportsMatrixView($a_obj_type)
Create styles array
The data for the language used.
static _lookupType($a_id, $a_reference=false)
lookup object type
getModeText($a_mode)
static supportsMark($a_obj_type)
static _mode2InfoText($a_mode)
static supportsSpentSeconds($a_obj_type)
static isLPMember(array &$a_res, $a_usr_id, $a_obj_ids)
Find (lp-relevant) members for given object ids.
static deleteObject($a_obj_id)
Delete object.
getMembers($a_search=true)
$ref_id
Definition: sahs_server.php:39
static _deleteReadEventsForUsers($a_obj_id, array $a_user_ids)
global $ilDB
static handleMove($a_source_ref_id)
static getLPMemberships($a_usr_id, array $a_obj_ids, $a_parent_ref_id=null, $a_mapped_ref_ids=false)
Get all objects where given user is member (from LP POV)
static getInstance($a_obj_id)
static _mode2Text($a_mode)